C++ 拷贝省略可见的副作用

C++ 拷贝省略可见的副作用,c++,c++11,copy-elision,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" &l

考虑以下代码:

#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;
}
#包括
使用名称空间std;
结构Foo{
公众:
int_a{};
Foo(int a):_a{a}
{

std::cout在特定情况下,将拷贝省略单独作为一种优化的整体要点是允许省略拷贝构造的副作用。也就是说,是的,尽管拷贝构造函数和/或析构函数有副作用,但拷贝省略还是会发生

如果您不希望在某些情况下发生复制省略,您需要安排将其禁用。在您的特定情况下,禁用复制省略确实有点烦人,但类似的操作应该可以做到:

template <typename T>
T const& inhibit(T const& ref) {
    return ref;
}
// ...
Foo b = inhibit<Foo>(10);
模板
恒定和抑制(恒定和参考){
返回ref;
}
// ...
Foo b=抑制(10);

确切地说,令人惊讶的原因是什么?它完全符合要求(是的,是预期的)行为–毕竟,复制省略的全部目的是,嗯,省略对复制构造函数的调用。当然这是正常的。如果复制省略必须遵循“仿佛”规则,那就不是一件事了。这就像任何其他允许的优化一样。@vsoftco:我可以补充一点,这可能会影响到你的唯一方式是当你编写一个brok时首先是复制构造器,也就是说,一个没有真正复制的构造器。这就是复制省略的含义…@ChristianHackl“hit you”可能不是正确的词,但是…像他这样的仪器复制构造器并不少见,这肯定会导致明显的副作用(但不应保留在交付代码中的部分——此类指令插入实际上仅用于调试)。另一种情况是,当类包含引用计数时,复制构造函数不应从源代码复制引用计数。(当然,大多数包含引用计数器的类可能不支持复制。)@vsoftco你真的应该设计你的代码,假设复制省略可能发生,而不是试图阻止它。@juanchopanza是的,我知道:)这是我在试图理解复制省略是如何工作的时候想到的。为什么编译器不能在通过附加层构造对象时执行复制省略,如上面的示例中所示?@vsoftco:copy省略只允许在一些特定的情况下使用。从内存中看,这些是复制临时的ary,返回一个命名对象,抛出一个命名对象,我认为还有一些我一直忘记的事情。但是,从函数返回的引用中删除副本不是其中之一。