计数运动会导致海森堡效应吗?

odi*_*erd 3 c++ optimization move c++11

这个问题(下面的代码)std :: async和object copy让我想到了复制/移动繁重的库实现.这个例如制作5份.对策可能很棘手,例如在async的情况下,通过引用传递而不是值可能导致并发问题.移动构造函数也并不总是便宜.

我的问题是,找到一种通过引用传递方式的对策真的可以解决不存在的问题吗?我假设大多数(如果不是全部)库函数最终都会被内联,它们通常只有一行或两行代码.我当然在输出中仍然得到五个"删除obj",因为编译器必须遵循as if规则.如果我要通过不打印来消除析构函数的副作用,那么似乎规则会更进一步并最终在发布版本中只有一个副本/移动吗?

在编写移动构造函数时是否应该注意以避免混淆编译器或无意中引入副作用并阻止它进行优化?

class obj {
public:
    int val;
    obj(int a) : val(a) {
        cout << "new obj" << endl;
    }
    ~obj() {
        cout << "delete obj" << endl;
    }
};

void foo(obj a) {
    this_thread::sleep_for(chrono::milliseconds(500));
    cout << a.val << endl;
}

int main(int argc, int **args) {
    obj a(5);
    auto future = async(foo, a);
    future.wait();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

And*_*owl 5

计数移动是否会导致海森堡效应?

不,不是真的.如果你的意思是对事件的观察改变了事件本身,我认为在这种情况下这是一个错误的比喻.

风险是你的观察会错过这个事件,好像你从未写过那些副作用.虽然一般,副作用,应根据"好像"规则(1.9/1)考虑由编译器,有几个重要的情况下的"仿佛"规则并不能适用:这种情况是副本时, /移动临时对象的省略可以由编译器执行.

允许这种情况的情况在C++ 11标准的第12.8/31段中有详细描述:

当满足某些条件时,允许实现省略类对象的复制/移动构造,即使该对象的复制/移动构造函数和/或析构函数具有副作用.在这种情况下,实现将省略的复制/移动操作的源和目标视为仅仅两种不同的引用同一对象的方式,并且该对象的销毁发生在两个对象的后期时间.没有优化就被破坏了.复制/移动操作的省略,称为复制省略,在下列情况下允许(可以合并以消除多份副本):[...]

然后该段继续列出具体情况.这与回答问题无关,所以我省略了它们.你可以去查找它们.

重要的是你的副作用可能会被跳过.如果std::async()执行某些副本或移动,取决于如何完成,编译器可能会忽略它们,即使你有一些打印输出,或者更一般地说,即使你有一些副作用.

因此,您不应该依赖副本构造函数中的副作用,移动构造函数或析构函数作为计算函数内执行了多少副本或移动的可移植方式:不同的编译器,不同的优化级别,当然还有不同的实现该功能可能产生不同的结果.