即使禁用了优化,Visual Studio 仍然可以进行优化吗?

4
我正在尝试使用移动和复制构造函数来学习它们,但遇到了一些奇怪的事情,让我有点困惑。基本上,我创建了一个类,并重载了构造函数、析构函数、复制构造函数和移动构造函数,以不同的方式构造它们,以查看构造函数是如何调用的。但我发现了一种调用顺序,结果并不如我所期望。请注意,我在这个例子中完全禁用了优化,并且在VS2012中进行编译。在这种情况下,内联是否仍然可能?
以下是我编写的源代码。
class RvalueTest
{
public:
    RvalueTest() {
        printf("CONSTRUCTOR\n");
    }

    RvalueTest(const RvalueTest& r) {
        printf("COPY CONSTRUCTOR\n");
    }

    RvalueTest(RvalueTest&& r) {
        printf("MOVE CONSTRUCTOR\n");
    }
};

__declspec(noinline)
RvalueTest GetRvalueTest() {
    return RvalueTest();
}

我随后使用以下代码进行测试。
RvalueTest t1;
RvalueTest t2(t1);
RvalueTest t3(GetRvalueTest());

我希望看到的是以下内容。
CONSTRUCTOR
COPY CONSTRUCTOR
CONSTRUCTOR
MOVE CONSTRUCTOR

我实际看到的是这样的。
CONSTRUCTOR
COPY CONSTRUCTOR
CONSTRUCTOR

看起来最后一行被合并到一个构造函数调用中,如果启用了优化,这是自然而然的。即使我完全关闭了优化,这种情况仍然会发生吗?更奇怪的是,如果我执行以下操作。

RvalueTest t1;
RvalueTest t2(t1);
RvalueTest t3(RvalueTest(GetRvalueTest()));

我得到了如下结果。
CONSTRUCTOR
COPY CONSTRUCTOR

你向编译器传递了哪些标志? - user657267
1个回答

4
在第一个示例中,编译器似乎确实省略了移动构造函数的调用。无论是否启用优化,以及被省略的复制/移动构造函数是否具有副作用,编译器都可以这样做。
在第二种情况下,你遇到了最令人烦恼的解析
RvalueTest t3(RvalueTest(GetRvalueTest()));

这定义了一个名为t3的函数,它接受一个指向带有签名RvalueTest(*)()的函数的指针,并通过值返回一个RvalueTest。使用大括号来修复此问题(可能无法在VS2012中工作)。
RvalueTest t3(RvalueTest{GetRvalueTest()});
//                      ^               ^

在进行了该更改后,我使用VS2013得到了以下输出:

CONSTRUCTOR
COPY CONSTRUCTOR
CONSTRUCTOR
MOVE CONSTRUCTOR

太好了!非常感谢。我早就有所怀疑。还有,感谢您提供的最令人困扰的解析链接。它确实名副其实。 - Morgan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接