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

《Effective C++》读书笔记(2):构造析构赋值运算

款5、了解C++默认编写并调用哪些函数 通常情况下,如果代码中没有声明构造函数、拷贝构造函数、拷贝运算符、析构函数,编译器会在需要时创建他们,但这往往只能满足编译器的需求,很可能无法满足程序的需求...不过这种操作只有在基类是多态用途时才需要注意,也有很多类不是为了多态的用途,例如STL容器和上文的Uncopyable。...对于派生类的构造函数而言,进入其中时基类部分已构造完而派生类部分未构造完,对象类型是基类,故而此时调用虚函数,实际上使用的是基类的虚函数。 析构函数同理。...进入析构函数后派生类部分呈未定义值,对象类型是基类,调用的是基类的虚函数。 总而言之,在构造函数与析构函数中虚函数的行为有特殊变化;为了避免出错,不要在其过程中使用虚函数。...那么这样简单的拷贝运算符就会出错,先释放了自身的pb,又使用了pb: Widget& Widget::operator=(const Widget& rhs){ delete pb; pb =

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

    ☀️ 学会编程入门必备 C# 最基础知识介绍(五)——方法、封装、继承、多态

    每一个 C# 程序至少有一个带有 Main 方法的类。 要使用一个方法,您需要: 定义方法 调用方法 ---- C# 中定义方法 当定义一个方法时,从根本上说是在声明它的结构的元素。...在 C# 中,有三种向方法传递参数的方式 方式 描述 值参数 这种方式复制参数的实际值给函数的形式参数,实参和形参使用的是两个不同内存中的值。...在 C# 中,使用 按引用传递参数 引用参数是一个对变量的内存位置的引用。当按引用传递参数时,与值参数不同的是,它不会为这些参数创建一个新的存储位置。...在静态多态性中,函数的响应是在编译时发生的。在动态多态性中,函数的响应是在运行时发生的。 在 C# 中,每个类型都是多态的,因为包括用户定义类型在内的所有类型都继承自 Object。...分别为: 函数重载 运算符重载 ---- 函数重载 可以在同一个范围内对相同的函数名有多个定义。函数的定义必须彼此不同,可以是参数列表中的参数类型不同,也可以是参数个数不同。

    95720

    一个面试题引发的思考——类的特种成员函数

    这些成员函数只有在代码中用到且没有声明时才会生成默认,即没有用到则不会生成。(见示例代码1) 关于默认构造函数:当类中不存在构造函数时,才会生成默认构造函数。...、拷贝赋值运算符、析构函数中的任何一个,就得同时声明这三个。...默认理解为声明这三个中的一个必定涉及到了资源管理,所以默认的拷贝操作也就不再适宜,所以均需要用户自定义。...、拷贝赋值运算符、析构函数、移动构造函数、移动赋值运算符中的任何一个,就得同时声明这五个。...如果声明了拷贝构造函数、拷贝赋值运算符、析构函数中的任何一个,必须同时声明这三个。 如果声明了移动操作中的一个则会抑制另一个的生成,因此,需要同时声明他们两个。

    7510

    学过 C++ 的你,不得不知的这 10 条细节!

    另外一个注意的是初始化次序(顺序),初始化次序(顺序): 先是基类对象,再初始化派生类对象(如果存在继承关系); 在类里成员变量总是以声明次序被初始化,如本例中 m_Id 先被初始化,再是 m_Name...构造函数最好使用成员初值列,而不要在构造函数本体内使用赋值操作。初值列列出的成员变量,其排列次序应该和它们在 class 中的声明次序(顺序)相同。...---- 细节 09:在 operator= 中处理「自我赋值」 「自我赋值」发生在对象被赋值给自己时: class A { ... }; A a; ... a = a; // 赋值给自己 这看起来有点愚蠢...我旧文里《C++ 赋值运算符'='的重载(浅拷贝、深拷贝)》在规避这个问题试,就采用的是方式 一,这个方式是不合适的。...---- 细节 10:复制对象时勿忘其每一个成分 在以下我把复制构造函数和赋值操作符函数,称为「copying 函数」。

    75520

    第 13 章 拷贝控制

    其中,拷贝和移动构造函数定义了当用同类型的另一个对象初始化本对象时做什么。拷贝和移动赋值运算符定义了将一个对象赋予同类型的另一个对象时做什么。...编译器略过了拷贝构造函数 在一个构造函数中,成员的初始化是在函数体执行之前完成的,且按照它们在类中出现的顺序进行初始化。...在重载拷贝赋值运算符时,要注意处理自赋值情况,一个较好的方法是在销毁左侧运算对象之前先拷贝右侧运算对象。 拷贝一个像值的对象时,副本和原对象是完全独立的。...可以通过标准库中的 move函数来显式地将一个左值转换为对应的右值引用类型。在对一个对象使用 move函数后,可以对这个移后源对象进行销毁或赋值操作,但不能再使用它!...v2 = getVec(cin); // 右侧对象是一个右值,使用移动赋值 使用拷贝并交换技术实现的赋值运算符,如果在类中同时定义了一个移动构造函数,则该赋值运算符实际上也是一个移动赋值运算符

    1K50

    C++:31---对象引用和赋值

    ,意味着此参数要进行拷贝初始化 依赖实参的类型,拷贝初始化: 要么使用拷贝构造函数——左值被拷贝 要么使用移动构造函数——右值被移动 因此,此处定义的赋值运算符就实现了拷贝赋值运算符和移动赋值运运算符的两种功能...例如: 第一个赋值中,右侧对象hp2是一个左值,因此使用拷贝构造函数来初始化 第二个赋值中,我们调用std::move()将将一个右值绑定到hp2上。...交换HasPtr回交换两个对象的指针(及int)成员。在swap之后,rhs中的指针将指向原来左侧对象所拥有的string(及int)。...; //s1+s2是一个右值,我们此处对一个右值进行了赋值(无意义) 在旧标准中,我们没有办法阻止这种使用方式。...,引用限定符只能作用于(非static)成员函数,且在声明和定义时都需要 引用限定符可以和const一起使用,且const必须在限定符的前面。

    1.8K10

    腾讯C++后台开发面试笔试知识点参考笔记

    如果析构函数不被声明成虚函数,则编译器实施静态绑定,在删除基类指针时,只会调用基类的析构函数而不调用派生类析构函数,这样就会造成派生类对象析构不完全。所以,将析构函数声明为虚函数是十分必要的。...只有成员函数中的代码才应该使用作用域操作符覆盖虚函数机制。 为什么会希望覆盖虚函数机制?最常见的理由是为了派生类虚函数调用基类中的版本。...在这种情况下,已经确切知道调用哪个实例,因此,不需要通过虚函数机制。派生类虚函数调用基类版本时,必须显式使用作用域操作符。...一般我们并不关心是哪个实际类包含成员,通常只在基类和派生类共享同一名字时才需要注意。 与基类成员同名的派生类成员将屏蔽对基类成员的直接访问。...(info1 == info2); } 复制控制 包括,一个拷贝构造函数,一个赋值运算符,一个析构函数,一对取址运算符 如果你这么写:class Empty{}; 和你这么写是一样的: class Empty

    1K10

    两万字总结《C++ Primer》要点

    拷贝构造函数、移动构造函数定义了当用同类型的另一个对象初始化本对象时做什么。 拷贝赋值运算符、移动赋值运算符定义了将一个对象赋予同类型的另一个对象时做什么。 析构函数定义了当此类型对象销毁时做什么。...移动赋值运算符: StrVec &StrVec::operator=(StrVec &&rhs) noexcept { } 合成的移动操作: 若一个类定义了自己的拷贝构造函数、拷贝赋值运算符或者析构函数...::: warning 当我么用一个派生类对象为一个基类对象初始化或赋值时,只有该派生类对象中的基类部分会被拷贝、移动或赋值,它的派生类部分会被忽略掉。...如果我们想拷贝(或移动)基类部分,则必须在派生类的构造函数初始值列表中显式的使用基类的拷贝(或移动)构造函数。 ::: 派生类的赋值运算符: 派生类的赋值运算符必须显式的为其基类部分赋值。...派生类的析构函数: 派生类函数只负责销毁由派生类自己分配的资源。 15.8 容器与继承 当使用容器存放继承体系中的对象时,必须采用间接存储的方式。因为不允许在容器中保存不同类型的元素。

    2.1K30

    两万字总结《C++ Primer》要点

    拷贝构造函数、移动构造函数定义了当用同类型的另一个对象初始化本对象时做什么。 拷贝赋值运算符、移动赋值运算符定义了将一个对象赋予同类型的另一个对象时做什么。 析构函数定义了当此类型对象销毁时做什么。...移动赋值运算符: StrVec &StrVec::operator=(StrVec &&rhs) noexcept { } 合成的移动操作: 若一个类定义了自己的拷贝构造函数、拷贝赋值运算符或者析构函数...::: warning 当我么用一个派生类对象为一个基类对象初始化或赋值时,只有该派生类对象中的基类部分会被拷贝、移动或赋值,它的派生类部分会被忽略掉。...如果我们想拷贝(或移动)基类部分,则必须在派生类的构造函数初始值列表中显式的使用基类的拷贝(或移动)构造函数。 ::: 派生类的赋值运算符: 派生类的赋值运算符必须显式的为其基类部分赋值。...派生类的析构函数: 派生类函数只负责销毁由派生类自己分配的资源。 15.8 容器与继承 当使用容器存放继承体系中的对象时,必须采用间接存储的方式。因为不允许在容器中保存不同类型的元素。

    1.8K20

    C++查缺补漏

    ,但它并不是万能的 在提供一个完整的类声明之前,不能声明该类的对象,也不能在内联成员函数中使用该类的对象 当使用前向引用声明时,只能使用被声明的符号,而不能涉及类的任何细节 class Fred; /...不需要显式地调用基类的析构函数,系统会自动隐式调用 先执行派生类析构函数的函数体,再调用基类的析构函数 访问从基类继承的成员 当派生类与基类中有相同成员时: 若未特别限定,则通过派生类对象使用的是派生类中的同名成员...注意: 在第一级继承时就要将共同基类设计为虚基类 虚基类及其派生类构造函数 建立对象时所指定的类称为最远派生类 虚基类的成员是由最远派生类的构造函数通过调用虚基类的构造函数进行初始化的 在整个继承结构中...这时,派生类的虚函数便覆盖了基类的虚函数 派生类中的虚函数还会隐藏基类中同名函数的所有其它重载形式 一般习惯于在派生类的函数中也使用virtual关键字,以增加程序的可读性 虚析构函数 为什么需要虚析构函数...list[i] = a.list[i]; } //重载"="运算符,将对象rhs赋值给本对象。

    2.6K10

    Effective_Cpp中的55个建议

    return *this; } 11:在operator=中处理自我赋值 w=w; a[i]=a[j]; *px=*py; 这几种都会发生“自我赋值”。...return *this; } 12:复制对象时勿忘其每一个成分 1.如果你自己写了一个拷贝构造函数或=运算符,那么如果你在里面落掉了某个成员,编译器是不会提醒你的。...3.还有如果一个子类继承了你的这个类,那么这个子类在调用拷贝函数时,就不会自动调用父类中你写的拷贝函数了,需要你手动调用。...++11之后,就已经弃用auto_ptr了,可以把auto_ptr改成shared_ptr 2.为防止资源泄露,请使用RAII(资源获取时机便是初始化时机)对象,他们在构造函数中获得资源并在析构函数中释放资源...3.切割问题:当使用传值方式时,一个子类对象被传递,被当一个父类对象接收时,此时只能调用父类中拥有的操作,子类扩展的就被切割了。 21:?必须返回对象时,别妄想返回其reference。

    60730

    Effective c++ 小结

    用 const的好处是,调试时,可以直接获取变量,而非定义的数字,这个在使用gdb跟踪代码的时候很有用,比如#define NUM 123;如果在gdb中print NUM,会出现NUM找不到符号表的问题...条款6:析构函数里对指针成员调用delete 这条为了防止内存泄露,具体说来要做三件事情:   每个构造函数中将该指针初始化   每个赋值运算符中将原有内存删除,重新配置一块   每个析构函数中...3,基本类型的non-const, non-reference对象,初始化和赋值之间没有2所说的区别 条款13: 初始化列表中成员列出的顺序和它们在类中声明的顺序相同 编译器构造和析构的顺序是相反的...String& String::operator =(const String&rhs) { … return *this; } 条款16: 在operator=中对所有数据成员赋值 原因:编译器会默认为你生成一个...(*this) = rhs两种方式解决 条款17: 在operator=中检查给自己赋值的情况 一般采用的方法: C& C::operator=(const C&rhs) {

    81050

    《C++Primer》第十三章 拷贝控制

    在一个析构函数中,不存在类似构造函数中初始化列表的东西来控制成员如何销毁,析构部分是隐式的。成员销毁时发生什么完全依赖于成员的类型。销毁类类型的成员需要执行成员自己的析构函数。...阻止拷贝 虽然大多数类应该定义拷贝构造函数和拷贝赋值运算符,但是对于某些类来说这些操作没有意义。在此情况下,在定义类时必须采用某种机制组织拷贝或者赋值。...rhs现在指向本对象曾经使用过的内存 return *this; // rhs被销毁,从而delete了rhs中的指针 } 这个技术自动就是异常安全的,且能正确处理自赋值: 在改变左侧对象之前就拷贝右侧运算对象...我们使用一个allocator来获取原始内存,由于allocator获取的原始内存是未构造的,我们将在需要添加新元素时使用constructor在原始内存中创建对象,在删除元素时使用destory销毁元素...如果vector使用的是拷贝构造函数并且发生异常,在新内存中构造元素时旧元素保持不变,这时候如果发生异常vector可以直接释放新分配(但还没构造成功)的内存并返回。vector中的元素仍然存在。

    1.6K40

    C++:51---继承中的构造函数、析构函数、拷贝控制一系列规则

    规则如下: 如果基类中的默认构造函数、拷贝构造函数、拷贝赋值运算符、或析构函数是被删除的或者是不可访问的,则派生类中对应的成员将是删除的,原因是编译器不能使用基类成员来执行派生类对象中属于基类的部分操作...当我们使用=default请求一个移动操作时,如果基类中的对应操作是删除的或不可访问的,那么派生类中该函数是被删除的,原因是派生类对象的基类部分不可移动。...virtual ~Quote() = default; //虚析构函数 }; 四、派生类的拷贝控制成员 派生类在执行拷贝构造函数/移动拷贝构造函数,或拷贝赋值运算符/移动赋值运算符时...(std::move(d)) //别忘记移动基类成员 { //在函数体内移动本类成员 } }; 派生类赋值运算符 与拷贝和移动构造函数一样,派生类的赋值运算符页必须显式地为其基类部分赋值: 例如: class...//为基类执行赋值运算符 //然后再执行本类的部分 return *this; } }; 五、特别注意:在构造函数和析构函数中调用虚函数 根据构造函数,析构函数我们知道: 派生类构造时,先构造基类部分

    1.5K30

    CC++学习之路(一)

    首先,我们先来弄懂关于构造函数的定义。在百度百科上,是这么定义的:构造函数 ,是一种特殊的方法。主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中。...(也称为拷贝构造函数)         //    复制构造函数参数为类对象本身的引用,用于根据一个已存在的对象复制出一个新的该类的对象,一般在函数中会将已存在对象的数据成员的值复制一份到新创建的对象中...// 也可以使用下面的形式         Complex c3 = Complex(1.0,2.5);                 //    把c3的数据成员的值赋值给c1        ...调用类型转换构造函数         //    系统首先调用类型转换构造函数,将5.2创建为一个本类的临时对象,然后调用等号运算符重载,将该临时对象赋值给c1         c2 = 5.2;        ...只定义指针而不给指针赋值,则不涉及内存分配,不调用构造函数。

    80631

    深入探讨 JavaScript 逻辑赋值运算符

    无条件 vs 有条件 数学运算符,例如 +是无条件的。 在const x = 1 + 2中,无论如何,我们总是将LHS添加到RHS中,并将结果分配给x。...LHS 和 RHS 是数学领域内的概念,意为等式左边和等式右边的意思,在我们现在的场景下就是赋值操作符的左侧和右侧。当变量出现在赋值操作符的左边时,就进行 LHS 查询;反之进行 RHS 查询 ?。...它将 LHS 添加到RHS,最后将其分配给x,得出2。 逻辑运算符,例如 &&是有条件的 在const x = true && 0 + 2中,首先计算 LHS,它为true。...二元逻辑运算符 && || ?? 在 JSX 中我们经常使用&&和||来有条件地渲染界面。??是nullish(空值)合并运算符,它是最近刚通过提案的,很快就会普及。它们都是 二元逻辑运算符。...; // 这里的 myObject.c 为虚值,所以什么都不会做 如何在项目中使用逻辑赋值 Chrome 已经支持逻辑赋值。 为了向后兼容,请使用 transformer。

    96420

    C++10中的移动语义

    首先,我们来看这样一个函数: (T为一个对象类型) T clone(const T& rhs) { T other = rhs; return other; } 这样的函数中...第一次默认拷贝构造函数的调用是在demo对象的初始化过程中; 两次拷贝构造函数实在clone函数的调用过程中: clone函数中利用this对象初始化demo对象进行一个拷贝构造,然后返回demo...如果源对象是在复制或者赋值结束以后被销毁的临时对象,编译器会使用两种方法。移动构造函数和移动赋值运算符将成员变量从源对象复制/移动到新对象,然后将源对象的变量设置为空值。...移动语义是通过右值引用实现的。在C++中,左值是可以获取其地址的一个量,例如有名称的变量。由于经常出现在赋值语句的左边,因此称其为左值。所有不是左值的量都是右值,例如常量、临时变量或者临时对象。...通常位于赋值运算符的右边。 右值引用是一个对右值的引用。特别地,这是一个当右值是临时对象时使用的概念。右值引用的目的是提供在临时对象时可选用的特定的方法。

    50030
    领券