考虑以下代码:
#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
输出
构造函数 构造函数 复制 0
这是我所期望的,因为Foo b = 10
,10
是从int
隐式构建的,然后b
是从Foo
构建的副本。此外,我的复制构造函数没有做任何事情,因此成员_a
仍为0
(因为它是在类中初始化的)。
然而,当我使用copy elision
时g ++ -std = c ++ 11 test.cpp
输出
构造函数 构造函数 10
令人惊讶至少可以说。我知道复制构造函数在这里被省略了,但这是一个严重的副作用(成员被初始化为0和一次到10的事实),因为它影响代码路径的其余部分。
这种行为是否正常?
答案 0 :(得分:3)
在特定情况下,单一复制省略作为优化的全部要点是允许复制构造的副作用。也就是说,是的,尽管复制构造函数和/或析构函数有副作用,它仍然期望复制省略。
如果您不希望在某些情况下发生复制,您需要安排禁止复制。在你的具体情况下,禁止复制省略无疑是有点烦人但是这样的事情应该可以解决这个问题:
template <typename T>
T const& inhibit(T const& ref) {
return ref;
}
// ...
Foo b = inhibit<Foo>(10);