c++ - 计算 Action 会导致海森堡效应吗?

标签 c++ optimization c++11 move

本题(代码如下)std::async and object copy让我开始考虑复制/move 繁重的库实现。例如,这个制作 5 个拷贝。对策可能很棘手,例如在异步的情况下,通过引用而不是值传递可能会导致并发问题。 move 构造函数也不总是便宜的。

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

在编写 move 构造函数时,我是否应该注意一些事情,以免混淆编译器或无意中引入副作用并阻止其优化?

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;
}

最佳答案

Does counting moves cause a Heisenberg effect?

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

风险在于您的观察会错过事件,就好像您从未写过这些副作用一样。虽然,一般,编译器应根据“as if”规则 (1.9/1) 考虑副作用,但在一些重要情况下,“as if”规则确实 strong>不适用:这种情况是编译器可以执行临时对象的复制/move 省略。

在 C++11 标准的第 12.8/31 段中精确描述了允许这样做的情况:

When certain criteria are met, an implementation is allowed to omit the copy/move construction of a class object, even if the copy/move constructor and/or destructor for the object have side effects. In such cases, the implementation treats the source and target of the omitted copy/move operation as simply two different ways of referring to the same object, and the destruction of that object occurs at the later of the times when the two objects would have been destroyed without the optimization. This elision of copy/move operations, called copy elision, is permitted in the following circumstances (which may be combined to eliminate multiple copies): [...]

然后该段继续列举具体情况是什么。这与回答问题无关,所以我省略了它们。你可以去看看。

重要的一点是您的副作用可能会被跳过。如果 std::async() 的实现执行了一些复制或 move ,这取决于它是如何完成的,编译器可能会忽略它们,即使你在那里有一些打印输出,或者更一般地说,即使您有一些副作用。

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

关于c++ - 计算 Action 会导致海森堡效应吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15040511/

相关文章:

c++ - 应用于基类列表的覆盖函数

MySQL:ORDER BY 或 GROUP BY 慢?

c++ - 基类和派生类中类成员变量的初始化

c++ - 为什么不能从初始化列表初始化我的类,即使它是从 std::list 派生的?

c++ - C++ Metro App 教程的编译错误 - 任务继续

c++ - 惯用STL : Iterating over a list and inserting elements

c++ - 从 ß 转换为 s c++

C#:通过内存有效搜索200万个对象,而无需外部依赖

c - 动态链接器 (ld.so) 中的运行时 cpu 检测

c++ - 如何在 C++11 中访问 double 的 pair<pair<string,string>,double>