1

考虑这段代码:

#include <iostream>

using namespace std;

struct Foo {
public:
    int _a{};
    Foo(int a) : _a{a} 
    {
        std::cout << "ctor" << std::endl;
    }

    Foo(const Foo &)
    {
        std::cout << "copy" << std::endl;
    }
};

int main () {
    Foo a{10};
    Foo b = 10;
    std::cout << b._a << std::endl;
}

当我编译时

g++ -std=c++11 -fno-elide-constructors test.cpp

输出是

ctor ctor 副本 0

这是我所期望的,因为 in Foo b = 10,10是从 隐式构造的int,然后b是从 构造的副本Foo。此外,我的复制构造函数不做任何事情,所以成员_a仍然存在0(因为它是类内初始化的)。

但是,当我使用复制省略时

g++ -std=c++11 test.cpp

输出是

演员 演员 10

至少可以说这是令人惊讶的。我知道这里省略了复制构造函数,但这是一个严重的副作用(成员一次初始化为 0 和一次初始化为 10 的事实),因为它会影响代码路径的其余部分。

这种行为正常吗?

4

1 回答 1

3

在特定情况下将复制省略作为优化的全部要点是允许省略复制构造的副作用。也就是说,是的,尽管复制构造函数和/或析构函数具有副作用,但它预计会发生复制省略。

如果您不希望在某些情况下发生复制省略,您需要安排它被禁止。在您的特定情况下,抑制复制省略诚然有点烦人,但这样的事情应该可以解决问题:

template <typename T>
T const& inhibit(T const& ref) {
    return ref;
}
// ...
Foo b = inhibit<Foo>(10);
于 2015-02-22T16:01:34.627 回答