【问题标题】:constructor or copy constructor?构造函数还是复制构造函数?
【发布时间】:2011-08-25 12:05:32
【问题描述】:

Generic Programming and the STL(中文版)一书中说:

X x = X() 将调用复制构造函数。

我觉得有点奇怪。我写了一个这样的测试程序

#include <iostream>

class Test {

public:

    Test() {
        std::cout << "This is ctor\n";
    }

    Test(const Test&) {
        std::cout << "This is copy-ctor\n";
    }

};

int main(int argc, char** argv)
{

    Test t = Test();
    return 0;
}

输出是“这是 ctor”。好的,现在我很困惑,这是对的吗?

【问题讨论】:

    标签: c++ constructor copy-constructor


    【解决方案1】:

    通常是的,默认构造一个临时对象,然后调用复制构造函数将其复制到您的对象t

    然而,实际上副本可以被优化出来——即使它有副作用(控制台输出):

    [n3290: 8.5/16]: [..] 在某些情况下,实现是 允许消除本固有的复制 通过直接构造中间结果来直接初始化 进入正在初始化的对象;见 12.2、12.8。

    And(结合同句中给出的例子):

    [n3290: 12.2/2]: [..] 一个实现可能使用一个临时的 in 在使用X 的副本将其传递给 f() 之前构造 X(2) 构造函数;或者,X(2) 可能会在空间中构建 用来持有论点。 [..]

    但是复制构造函数确实仍然必须存在,即使它可能不会被调用。

    无论如何,如果您在关闭优化的情况下进行编译(或者,使用 GCC,可能是 -fno-elide-constructors),您会看到:

    This is ctor
    This is copy-ctor
    

    【讨论】:

    • 在 gcc 中,您可能必须使用 -fno-elide-constructors,因为我认为即使 -O0 也不能防止省略。
    • 即使副本不是平凡,也可以省略副本,通过构造临时变量代替局部变量来省略副本。对象或副本的复杂性与优化无关。
    • @Tomalak:感谢 discovering that option 的史蒂夫·杰索普(和 +50) :-)
    • 现在等待。你不是前几天对那些只用两句话开始回答然后逐渐扩展的人如此生气的人吗? :)
    • @sbi:啊,但我的回答即使是最简单的形式也是正确的。 IIRC 前几天,我被一个开始生活的答案激怒了,基本上,“答案即将到来......”
    【解决方案2】:

    理论上,X x = X() 将调用默认构造函数来创建一个临时对象,并使用复制构造函数将其复制到x

    实际上,允许编译器跳过复制构造部分并直接默认构造x(正如大卫在他的评论中指出的那样,仍然需要复制构造函数在语法上是可访问的)。大多数编译器至少在启用优化时会这样做。

    【讨论】:

    • 重要的是要注意复制构造函数必须可用,即使复制被省略。也就是说,如果它不可访问,编译器将拒绝该行并出现错误。
    • @David:你是对的。我已将其纳入我的答案。感谢您提出这个问题。
    【解决方案3】:

    在这种情况下,Return Value Optimisation(RVO)(也称为Copy Elision)的形式对优化有很大帮助。链接的维基百科页面很好地解释了正在发生的事情。

    【讨论】:

    • 我认为这并不完全正确。这里没有返回X 的函数调用(请记住,构造函数没有返回值)。这是复制省略,这是一个相关但不同的概念。
    • 我同意。这不是严格意义上的 RVO(尽管它是相关的)。
    • @Tomak:这也不完全不正确。这是那种优化的变体。 +1 以抵消反对票。
    • @Prasoon:平衡是错误的。剥夺他人的投票权不是你的工作。
    • 而且,即使 RVO 是一个合适的术语,如果没有别的,这个答案并不能真正解释 OP 的代码发生了什么。仅仅因为这个原因,这不是一个好的回应。
    猜你喜欢
    • 2013-06-12
    • 2013-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-14
    • 2016-09-12
    • 2015-03-06
    相关资源
    最近更新 更多