复制省略可见的副作用

时间:2015-02-22 15:55:17

标签: c++ c++11 copy-elision

考虑以下代码:

#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 = 1010是从int隐式构建的,然后b是从Foo构建的副本。此外,我的复制构造函数没有做任何事情,因此成员_a仍为0(因为它是在类中初始化的)。

然而,当我使用copy elision

  

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

输出

  

构造函数   构造函数   10

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

这种行为是否正常?

1 个答案:

答案 0 :(得分:3)

在特定情况下,单一复制省略作为优化的全部要点是允许复制构造的副作用。也就是说,是的,尽管复制构造函数和/或析构函数有副作用,它仍然期望复制省略。

如果您不希望在某些情况下发生复制,您需要安排禁止复制。在你的具体情况下,禁止复制省略无疑是有点烦人但是这样的事情应该可以解决这个问题:

template <typename T>
T const& inhibit(T const& ref) {
    return ref;
}
// ...
Foo b = inhibit<Foo>(10);