0

我一直在阅读有关复制省略和返回值优化如何通过避免调用对象复制构造函数来提高速度的信息。我了解这些机制是如何工作的,但我想知道这是否会导致程序的行为与预期不同。

本质上,我的问题是;如果我们编写复制构造函数而不创建作为另一个对象副本的对象会发生什么?换句话说,如果

AClass original;
AClass copy ( original );
// copy == original -> false

比如说,我们有一个这样的类:

// AClass.hpp

struct AClass
{
    static int copyCount;
    int copyNumber;

    AClass():copyNumber(0){}
    AClass( AClass const& original ):copyNumber(++copyCount){} // I think this is the signature for the copy constructor
};


// AClass.cpp

int AClass::count ( 0 );

这显然是一种可怕的行为,我并不是说我会做这样的事情。然而,重点是存在的;如果我们依赖副本的副作用怎么办?在此示例中,跟踪我们制作了多少副本。我希望优化不应该影响程序的运行方式。但是,复制省略可能会导致以下代码失败:

// Main.cpp

AClass MakeAClass()
{
    return AClass();
}

int main()
{
    AClass copy ( MakeAClass() );

    if ( AClass::copyCount == 1 )
    {
        return 0;
    }
    else
    {
        return -1;
    }
}

当我在没有优化的调试模式下构建时,这可能会返回 0,但是当我打开优化并且从 MakeAClass 的返回直接放在副本上时突然失败,跳过了复制构造函数。

当编译器尝试这些优化以寻找副作用时,是否有检查?当您要求副本时,期望代码执行副本是错误的吗?

4

1 回答 1

1

是的。如果您的复制构造函数(或移动构造函数或析构函数)有副作用,复制省略可以改变代码的行为。

这就是重点。如果它不能改变行为,就没有理由在标准中提及它。as-if 规则已经涵盖了不改变行为的优化。(1.9/1) 即:

本国际标准中的语义描述定义了一个参数化的非确定性抽象机。本国际标准对一致性实现的结构没有要求。特别是,它们不需要复制或模仿抽象机器的结构。相反,需要符合要求的实现来模拟(仅)抽象机器的可观察行为,如下所述。

标准中明确提到了复制省略,因为它可能违反了这条规则。

于 2014-04-09T04:46:27.913 回答