首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

C++初阶 类和对象(下)

拷贝构造函数只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰),在用已存在的类类型对象创建新对象时由编译器自动调用。 1.2 为什么得是引用?...为什么这个形参得是被类对象的引用呢,我直接传递我这个要拷贝的目标不可以吗,不是一样的操作吗。...类型的变量,那么它也会走向这个拷贝构造函数,于是拷贝构造函数调用拷贝构造函数,再调用拷贝构造函数....... 1.3 使用拷贝构造函数 简单的拷贝并打印一下,代码什么的自己去敲一遍效果好一些,别光看...,至于为什么要加const是因为我们传递过去的变量是被拷贝的,是不会被修改的 加个const是为了避免一些低级错误的发生,比方说修改到了被拷贝的对象,同时增加了代码的可读性。...比方说,我们现在实现的日期类的拷贝构造函数,其实只是涉及到了一个简单的值拷贝,而到后期我们使用什么栈啊,堆啊,二叉树之类的东西,我们如果还是简单地进行值拷贝,我们拷贝的东西不就只有一具空壳吗,我们得采取一些方式实现深拷贝

16310

带右值引用的拷贝构造函数和运算符重载函数

考虑一个占用堆资源类对象的拷贝构造和赋值运算符重载函数,当我们用一个临时对象去拷贝构造一个新对象或者赋值给一个已经存在的对象时,会出现一下的问题:如string类 #include ...() { MyString s1("aaaaaaaaaaaaaaaaaaaaaaaaaaa"); MyString s2; s2 = getString(s1); return 0; } 1.当我们用临时对象去拷贝构造一个新对象时...这样做一方面避免了在原来拷贝构造函数需要首先申请空间,然后进行拷贝的麻烦。另一方面避免临时对象析构时还有释放堆资源的麻烦,一举两得!!!...这里同样存在着上边的问题,我临时对象给你赋值完我就析构了,堆资源也在析构函数中被释放了,但是你被赋值的对象还得申请空间,还得拷贝,你直接用临时对象的那块堆资源不就好了。...在实际开发中,当出现一定要用临时对象作为返回值,要用临时来进行赋值时,我们可以为其类实现带右值引用的拷贝构造函数和运算符重载函数,在程序的效率上会得到很大的提升。

76620
  • 您找到你想要的搜索结果了吗?
    是的
    没有找到

    cc++常见面试题

    当我们同时编译多个文件时,所有未加static前缀的全局变量和函数都具有全局可见性,故使用static在不同的文件中定义同名函数和同名变量,而不必担心命名冲突。...区别: 1)const是有数据类型的常量,而宏常量没有,编译器可以对前者进行静态类型安全检查,对后者仅是字符替换,没有类型安全检查,而且在字符替换时可能会产生意料不到的错误(边际效应)。...RTTI事指运行时类型识别(Run-time type identification)在只有一个指向基类的指针或引用时确定一个对象的准确类型。 14. 什么是拷贝构造函数?...它是单个参数的构造函数,其参数是与它同属一类的对象的(常)引用;类定义中,如果未提供自己的拷贝构造函数,C++提供一个默认拷贝构造函数,该默认拷贝构造函数完成一个成员到一个成员的拷贝 15....浅拷贝是创建了一个对象用一个现成的对象初始化它的时候只是复制了成员(简单赋值)而没有拷贝分配给成员的资源(如给其指针变量成员分配了动态内存); 深拷贝是当一个对象创建时,如果分配了资源,就需要定义自己的拷贝构造函数

    62030

    保护模式-第4讲-段-段跨越段权限

    运行在ring0中....只要 CPL RPL <= 3都可以访问. 1.2.2 CPL RPL DPL的检查 CPL RPL DPL我么知道是啥了.那么我么可以进行模拟....那么我们就可以将这个代码段 拷贝到GDT表数组中要给新的地方. 最后构造段选择子 让其访问即可. 从GDT表中拷贝一个代码段到GDT中没有使用的位置 观察上图.我们看GDT的时候....r gdtr dq GDTbase eq 地址 拷贝的内容 dq GDTBASE 图中遮挡的不要看.因为这是我实验之后没有修改回去而产生的错误项. 只需要看黑框一栏即可....通过以上指令我们可以看到 将GDT表中的第四项,拷贝到了 第16项中. 下面就是构造段选择子 然后进行跨段实验 3.段选择子构造 以及跨段实验 我们所添加的新项在 GDT表中的第16项.

    1.2K30

    一文入魂:妈妈再也不用担心我不懂C++移动语义了!

    一、为什么要有移动语义 (一)从拷贝说起 我们知道,C++中有拷贝构造函数和拷贝赋值运算符。那既然是拷贝,听上去就是开销很大的操作。...(三)当我们定义了拷贝操作之后 如果我们在类中定义了拷贝构造函数或者拷贝赋值运算符,那么编译器就不会自动生成移动构造函数和移动赋值运算符。...所谓强异常保证,即当我们调用一个函数时,如果发生了异常,那么应用程序的状态能够回滚到函数调用之前: 那么强异常保证和决定使用移动语义或拷贝操作又有什么关系呢?...为什么必须保证这一点呢?这是因为被移动对象只是处于一个特殊的状态,对于运行时来说,仍然是有效的,最终也会执行析构函数进行销毁。...因此,当返回局部对象时,我们不用画蛇添足,直接返回对象即可,编译器会优先使用最佳的NRVO,在没有NRVO的情况下,会尝试执行移动构造函数,最后才是开销最大的拷贝构造函数。

    1.3K20

    这 5 道 Java 面试题,你还真不一定懂。

    这里我给大家解释下 1a = a + "bc"; 这段代码究竟发生了什么,它是怎么生成 "abc"这个对象的。...例如内存不够用时的 OutOfMemoryError、Java 虚拟机运行时错误(VirtualMachineError)。...HashMap 的容量为什么是 2 的幂次方 HashMap 的底层原理是 数组 + 链表,当我们进行 put() 操作的时候,需要根据 key 来获取哈希码,一般获取的操作如下 1int hash =...拓展 当我们指定了初始容量为 initCapatity 时,那么系统就会把初始容量设置为比 initCapatity 大并且这个数是 2 的幂次方。...这里我说一下JDK1.8之后为何会出现红黑树,其实是这样的,当链表很多之后,就会影响查询操作,所以到了 JDK1.8之后,当链表的长度到了一定的阈值,就会把链表转换为红黑树,默认阈值为 8。

    59040

    golang语言是如何处理栈的

    不过Go核心团队正在尝试切换到另外一种方案,这里我将尝试阐述旧方案以及它的缺点,新方案以及为何要 做出如此改变。...它也是Go核心开发组更换到一个新的栈管理方案-栈拷贝(stack copying)的主要原因。 五、栈拷贝(stack copying) 栈拷贝初始阶段与分段栈类似。...当我们移动栈时,我们可以更新栈里地指针使其指向新的 目标地址,并且所有相关的指针都要被照顾到。 由于我们使用垃圾回收的信息来协助完成栈拷贝,因此所有出现在栈上的函数都必须具备这些信息。...因为Go运行时的大部分代码是 用C编写的,大量的运行时调用没有指针信息可用,这样就无法进行拷贝。一旦这种情况发生,我们又不得不退回到分段栈方案,并接受为其付出的高昂代 价。...如果你想了解更 多关于栈拷贝的细节,可以参考其设计文档。此外,如果你想了解更多有关Go运行 时重写的细节,这里有一个mail list。

    1.3K80

    C嘎嘎入门篇:类和对象(2)

    Init函数的,这便是构造函数的概念,当我们了解完概念以后,下面就要开始进入构造函数的特点讲解了!...,之后我们再往后看,后面这句话告诉我们我们在书写拷贝构造函数的时候一定要传引用,而不是去直接传类类型的对象,对于这个原因,小编就从这里开始进行解释,这里就牵扯到了下一个特点:当我们在调用类类型对象的时候...,会先进行一次拷贝构造以后在传过去,这个点各位读者朋友一定要记住,对于为什么这样做,小编也不是很清楚(理直气壮),这涉及到了深拷贝和浅拷贝,以后小编了解多了以后会在进行补充,所以这个点就说明了为什么我们要传引用...,如果直接传类类型的时候,会先去进行一次拷贝构造,如果我们不写出这个拷贝构造的话,那么会一直循环去找拷贝构造,从而造成死循环,这就是为什么会在语法逻辑上无限递归。...,于是我拖到现在才写完,这里我得批评下自己,太懒了,所以这篇文章跨越的时间有点长,所以可能会出现有一些语言的不搭,希望各位读者朋友理解,如果文章有错误的话,可以在评论区指出,小编会及时的回复,那么,我们下一篇文章见啦

    9210

    类和对象竟是这样的(中集)

    我们写了构造函数编译器又不生成默认构造函数,但是当我们没写构造函数时,编译器生成的默认构造函数又不初始化变量,可是通过调试知道,这个默认构造函数没有初始化变量,_year/_month/_day还是随机值...2.特性 (1)拷贝构造函数是构造函数的重载 (2)拷贝构造函数有且只有一个参数且为类类型对象的引用 ,返回类型为类类型 (3)当用户没有显示定义拷贝构造函数时,编译器会生成一个默认的拷贝构造函数,按内存顺序字节顺序直接复制拷贝...,这种拷贝称为浅拷贝,也叫值拷贝(与上面一样,对于内置类型直接根据字节拷贝,对于自定义类型调用它的拷贝构造函数) (4)若类中没有涉及到资源的申请,则写不写拷贝构造函数都行,而如果涉及到了,则必须写拷贝构造函数...最后一点,当我们没有显示定义赋值运算符函数时,编译器会自动生成一个函数,以值的方式逐字节拷贝,对于内置类型直接实施复制,对于自定义类型回去调用他的赋值运算符函数。...bb,没人告诉我错误就寄了。

    6910

    《C++Primer》第十五章 面向对象程序设计

    如果我们使用override标记了某个函数但是该函数没有覆盖已存在的虚函数,此时编译器将报错。 我们还可以把某个函数指定为final,之后任何尝试覆盖该函数的操作都将引发错误。 4....只要基类的析构函数是虚函数,就能确保当我们delete基类指针时将运行正确的析构函数版本。 我们之前介绍过一条经验准则:如果一个类需要析构函数,那么它同样也需要拷贝和赋值操作。...例如: 合成的Bulk_quote默认构造函数运行Disc_quote的默认构造函数,后者又运行Quote的默认构造函数 合成的Bulk_quote拷贝构造函数使用(合成的)Disc_quote拷贝构造函数...当我们为派生类定义拷贝或者移动构造函数时,我们通常使用对应的基类构造函数初始化对象的基类部分: // 初始值Base(d)将一个D对象传递给基类构造函数,Base(d)会去匹配Base的拷贝构造函数,将...默认、拷贝和移动构造函数不会被继承,这些构造函数会按照正常规则被合成,因此如果一个类只含有继承的构造函数,则它也将拥有一个合成的默认构造函数 容器与继承 当我们使用容器存放继承体系中的对象时,必须采用间接存储的方式

    1.2K20

    【C++篇】手撕 C++ string 类:从零实现到深入剖析的模拟之路

    和 s2 共享同一块内存 // 当程序结束时,析构函数会尝试两次释放同一块内存,导致程序崩溃 } 问题分析:浅拷贝的默认行为只复制指针的值,即 s1 和 s2 都指向同一个内存区域。...因此,当程序执行析构函数时,会尝试两次释放同一块内存,导致程序崩溃。 2.3 深拷贝的解决方案 为了避免浅拷贝带来的问题,我们需要在拷贝构造函数中实现深拷贝。...在C++中,当我们将一个对象赋值给另一个对象时,默认情况下,编译器会为我们生成一个浅拷贝的赋值运算符。...这意味着赋值后的对象和原对象会共享同一个内存空间,这会导致和浅拷贝相同的潜在问题,特别是在一个对象被销毁时,另一个对象继续使用该内存区域会引发错误。...因此,const 静态成员变量的值必须在类加载时确定,并且在整个程序运行过程中保持不变。 但是 const 静态成员的值不能在对象实例化时通过构造函数来提供,必须直接在类级别初始化。

    28920

    《深入理解拷贝构造函数:对象复制的核心机制》

    这个引用参数就像是一把钥匙,告诉拷贝构造函数要复制哪个对象。为什么是引用呢?这是为了避免在传递参数时进行不必要的复制。...五、拷贝构造函数的调用时机 (一)对象初始化 当我们用一个已存在的对象来初始化一个新对象时,拷贝构造函数就会被调用。...例如,如果我们有一个函数  void printPerson(Person p) ,当我们调用这个函数并传入一个  Person  对象时,就会调用  Person  类的拷贝构造函数来创建一个新的  ...了解拷贝构造函数的原理、特点和调用时机,能够帮助我们更好地设计和实现高质量的 C++ 程序,避免因为对象复制问题而导致的各种错误和性能问题。...在编程的旅程中,拷贝构造函数就像一个忠实的伙伴,陪伴我们处理对象复制的每一个细节,保障程序的顺利运行。

    10810

    【C++修炼之路】3. 类和对象(中)

    下面就来看看: 对于编译器来说,传值的错误是可以识别的,但只说了不能,而没有说为什么不能。...当然,经过询问这个问题和考虑之后,我明白无论什么类型的指针,它都算是一个内置类型,因为指针的值无论什么类型他都是一个地址,而对于这些默认函数来说,是不会对内置类型进行操作的,直接拷贝就可以,因此这个错误的想法就这么被推翻了...但是对于_a来说,是行不通的,因为我们不仅将值拷贝了过去,事实上,根本算不上拷贝,因为他们的地址都是一样的,当我们运行结束,每一个类对应的每一个对象都会通过析构函数销毁,然而因为地址相同的变量却销毁了两次...注意:类中如果没有涉及资源申请时,拷贝构造函数是否写都可以;一旦涉及到资源申请时,则拷贝构造函数是一定要写的(即必须写深拷贝),否则就是浅拷贝。...默认的赋值运算符重载 我们知道对于默认的6个成员函数都有一个共性,即当我们不写这样的函数时系统会默认生成一个这样的函数,前面的构造、拷贝、拷贝构造都已经展示过,下面将我们的赋值运算符重载函数去掉,让系统自动生成一个赋值运算符重载函数再运行会是什么样的结果

    52200

    C++智能指针

    而为什么不会像auto_ptr这样犯糊涂了,这是因为这次有了先锋者,C++委员会一部分人作为先锋者,对C++一些语法做了很多的尝试,最终形成的产物就是boost库,而C++11就是吸取boost库中精华的部分...在对象被销毁时(也就是析构函数调用),就说明自己不使用该资源了,对象的引用计数减一。...那么我们就来分析一下,这个代码为什么会内存泄漏: 首先,假设n1的生命周期先到,那么n1调用析构函数,n1的引用计数减一,剩余1。...然后n2的生命周期也到了,调用n2的析构函数,n2的引用计数也自减,剩余1。我们知道,只有当引用计数为0的时候才会delete, 否则只减去引用计数。..._prev管理着n1,当n2 delete时,会自动调用n1的析构函数),而n2要想析构,需要n1先析构(n1._next管理着n2,当n1被delete时,会自动调用n2的析构函数)。

    9010

    【细品C++】深入了解类和对象(六大默认成员函数以及操作符重载)

    到了本篇文章就真正开始到了类和对象真正难啃的地方了。本篇文章聚焦于类的6个默认成员函数的讲解,希望对你有所帮助。 类的6个默认成员函数 在上一篇文章中,我提到过空类,也就是什么成员都没有的类。...d1.Print(); date d2; //调用无参构造函数 d2.Print(); return 0; } 运行截图: 注意事项: int main() { //注意:使用无参构造函数定义变量时...: 可以看到,程序运行结束后输出了~Time(),而在main中并没直接创建Time类对象,为什么最后会调用Time类的析构函数?...而C++中,当我们创建一个自定义类型对象时,我们当然希望能够像内置类型一样,能够轻易使用一个已存在的该类型对象以初始化该对象。于是,就有了拷贝构造函数。...: 原因分析: 注意:类中如果没有涉及资源申请时,拷贝构造函数是否写都可以;一旦涉及到资源申请时,则拷贝构造函数是一定要写的,否则就是浅拷贝。

    91020

    【c++】类和对象(中)(构造函数、析构函数、拷贝构造、赋值重载)

    当我们在类中没有显示地定义构造函数时,编译器会自动生成一个无参的构造函数,用于创建对象时的初始化。一旦用户显示定义了构造函数之后,编译器则不会生成。 6....当我们没有在类中显示定义析构函数时,编译器会自动生成一个析构函数,供对象调用。...接下来我们尝试写一个拷贝构造函数并且使用它: #include using namespace std; class MyClass { public: //构造函数 MyClass...如果有写析构函数,那么通常需要写拷贝构造。 当我们在某个函数当中将对象作为返回值时,由于这个返回值是一份临时拷贝,所以会自动调用拷贝构造函数,造成运行效率的下降。...*pf)(); } 运行结果: 可以看到,运行成功了。这里我们在调用函数时,就使用到了“ .* ”运算符,它用于通过函数指针调用类的成员函数。

    17310

    Kotlin的面向对象编程,深入讨论继承写法的问题

    当时提到了一个Kotlin在继承时括号书写的问题,这部分内容比较有疑惑性,不太利于初学者理解。本来我是计划在直播时要讲这个问题的,但由于时间实在不够后来还是跳过了这部分内容。...之所以这么设计,是因为当我们调用了某个类的构造函数时,我们的意图只可能是对这个类进行实例化,因此即使没有new关键字也能清晰表达出我们的意图。...对于初学Kotlin的来人讲,这对括号确实挺难理解的,也可能是Kotlin在这方面设计得太复杂了,因为它还牵扯到主构造函数、次构造函数等方面的知识,这里我尽量尝试用最简单易懂的讲述来让大家理解这对括号的意义和作用...这里出现错误的原因也很明显,Person类后面的空括号表示要去调用Person类中无参的构造函数,但是Person类现在已经没有无参的构造函数了,所以就提示了上述错误。...Kotlin规定,当一个类既有主构造函数又有次构造函数时,所有的次构造函数都必须得调用主构造函数(包括间接调用),这里我通过一个具体的例子就能简单阐明清楚了,代码如下: class Student(val

    85230

    Effective Modern C++翻译(1):序言

    如果读者找到了完整的版本,欢迎大家发给我。...对为什么const成员函数应该是线程安全的感兴趣?如何使用std::unique_ptr实现pimpl?为什么你在使用lambda表达式时应该避免默认的变量捕捉形式?...当我提到C++98的时候,我指的只是C++语言的这个版本,当我提到C++11的时候,我指的是C++11和C++14,因为C++14是C++11的一个有效的超集,当我写C++14的时候,我明确的指的是C+...我把参数命名为rhs,代表了right-hand side,这是我在使用移动操作(比如移动构造,移动赋值)和拷贝操作(比如拷贝构造,拷贝赋值)时比较偏爱的名字,尽管我在使用二元运算符也通常使用rhs作为右面参数的名字...someFunc的参数w的时,你无法知道创建参数w所需要的花费(你同样需要知道拷贝构造和一个构造widget的花费)。

    1.2K90

    机器学习模型的特征监控方案设计

    为什么要做特征监控 举一个例子: 眼看着双十一快要到了,公司要做大促,实现留存拉新的目标,但面临一个棘手的问题:总是有专业羊毛党来薅羊毛。...BOSS想到了公司新招了个算法调包侠小王,于是找到了他,让他做一个识别羊毛党的模型。 小王开始了工作,构造训练集、选模型、调参、测试... 训练集的数据如下所示: ?...BOSS找到了小王:”你这咋回事,我们这么多客户,怎么一个羊毛党都发现不了???“ ? ? ? 小王也纳闷:线下效果很好啊,这是为什么? ? ? ? 赶紧去查看历史日志信息,迅速发现了问题: ?...所以导致所有的预测都是错误的! 虽然很快找到了原因,但两周的时间仍然产生了诸多问题: 公司损失了很多钱。 开发人员没有及时发现此问题。 开发人员本可以及时发现它并提供一个修复。...当我们在某些领域开展业务时,往往面临的一个挑战是,我们模型的预测结果具有迟滞性。也就是说当我们注意到这个问题时,问题已经发生了。

    2.3K40

    【C++修炼之路】10. vector类

    (nullptr) { reserve(n); for(size_t i = 0; i < n; i++) { push_back(val); } } 当我们将第二个拷贝构造的现代写法的拷贝构造和第三个构造并初始化...;直接改成int的话,不符合库的思想 //而且通过源代码也可以看出这里用到了:再加上一个重载函数的方式 //vector v1(10, 'A');//肯定会选择val对应的构造函数...然而事与愿违,并没有成功打印反而运行错误,因此我们可以断定,v1并没有像我们想的那样去调用第三种函数,我们通过观察上面的错误信息,发现,其调用的是迭代器初始化,即构造函数现代写法中的vector(InputIterator...对于vector(size_t n, const T& val = T())函数来说,当我们传入都是int类型时,前者n由于是size_t而不是int类型,调用此函数就会发生隐式类型转换,因此v1就会继续观察是否有更好的选择...那我们为什么不直接将上一个函数的size_t改成int类型呢?

    46800
    领券