编译器为具有引用和常量成员的类生成了复制/赋值函数

Compiler-generated copy/assignment functions for classes with reference and const members

本文关键字:复制 函数 赋值 引用 成员 常量 编译器      更新时间:2023-10-16

我正在读的书中说,当类包含引用或常量的成员时,使用编译器生成的复制构造函数或赋值运算符将不起作用。例如,

#include <iostream>
#include <string>
using namespace std;
class TextBlock
{
    public:
        TextBlock (string str) : s(str) {
            cout << "Constructor is being called" << endl;
        }
        string& s;
};

int main () {
    TextBlock p("foo");
    TextBlock q(p);
    q = p;
    cout << "Q's s is " << q.s << endl;
    return(0);
}

根据我的书,TextBlock q(p);q = p;这两行都应该返回编译器错误。但是使用Linux版的g++编译器,我只在q = p;行得到一个错误。当我注释掉它时,这很好,代码也会编译。正确的s是Q的输出,所以它显然是由编译器生成的复制构造函数复制的。当我将线string& s;更改为const string s时,我得到了相同的结果。

C++是否有一些更改,现在允许为引用和常量对象自动生成复制构造函数,但不允许为赋值运算符生成复制构造函数?或者我只是没有正确理解这本书?有什么想法吗?

这本书错了。常量成员或引用成员将禁止生成默认的副本分配运算符,但是不会阻止编译器生成复制构造函数。

不要试图在这里学习特殊规则。

编译器生成的特殊成员函数的默认版本遵循一个简单的模式:

  • 为每个子对象(基类和成员)调用适合类型的特殊成员函数

由此,你可以计算出每一个案例。

int i;
int &ri1 = i;
int &ri2 = ri1;

因此允许复制包含int&的对象。

引用没有赋值运算符(ri2 = ri1;不重新绑定引用),因此不允许赋值。

引用不能默认构造:

int& ri; // error

因此不能默认构造包含CCD_ 8的类型。

一个重要的考虑因素是对编译器默认代码进行访问检查,就像您自己编写的一样。因此,如果基类有一个私有的复制构造函数,那么有趣的事情就会发生。。。你不必为他们中的任何一个学习特殊规则。