【问题标题】:Compiler-generated copy/assignment functions for classes with reference and const members编译器为具有引用和 const 成员的类生成的复制/赋值函数
【发布时间】:2014-06-06 00:19:43
【问题描述】:

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

#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&amp; s; 更改为 const string s 时,我得到了相同的结果。

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

【问题讨论】:

  • 请注意,TextBlock p("foo"); 是未定义的行为。你最终会得到一个悬空的引用。
  • @JamesKanze 成员引用绑定到构造函数的参数取值。
  • @JamesKanze 在构造函数中有一个临时的string,引用绑定到那个。
  • 感谢您向我指出这一点,@juanchopanza。
  • @juanchopanza 啊。我看的不够近。 (我从未见过通过值传递 std::string 的代码。通常的规则是类类型总是通过引用传递给 const。)

标签: c++ compiler-construction copy-constructor assignment-operator


【解决方案1】:

这本书是错的。一个 const 成员或一个引用成员将 禁止生成默认的复制赋值运算符,但 不会阻止编译器生成复制构造函数。

【讨论】:

  • 感谢您的信息。你能解释一下这背后的原因/提供一个我可以阅读推理的来源吗?根据这本书,两者都没有意义,因为在复制情况下应该如何复制引用或常量成员是未定义的。如果不是这样,我想进一步了解。
  • @user2242700:这与所有其他成员和基础子对象的规则相同——默认复制构造函数使用与成员类型对应的复制构造函数复制它们。 const 类型的复制构造函数工作得很好。 const 对象构造后不能更改,但const 不会干扰构造。
  • @Ben Voigt 谢谢你的解释。
  • @BenVoigt 当然,同样的事情也适用于参考。 (对于其余部分,第 12.8 节正式解释了所有细节。但实际上,Ben 的评论完美地总结了它:如果你可以复制它,编译器将生成一个复制构造函数。)
【解决方案2】:

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

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

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

由此,您可以解决每个案例。

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

是允许的,因此允许复制包含int&amp; 的对象。

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

引用不能被默认构造:

int& ri; // error

所以包含int&amp; 的类型不能被默认构造。

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

【讨论】:

  • 谢谢,这条规则很有帮助。
猜你喜欢
  • 1970-01-01
  • 2015-02-22
  • 1970-01-01
  • 2014-10-07
  • 2012-01-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-24
相关资源
最近更新 更多