C++11 为什么调用复制构造函数而不是移动构造函数?
请查看以下示例代码:C++11 为什么调用复制构造函数而不是移动构造函数?,c++11,copy-constructor,move-semantics,rvalue-reference,rvo,C++11,Copy Constructor,Move Semantics,Rvalue Reference,Rvo,请查看以下示例代码: #include <iostream> struct Foo { Foo() { std::cout << "Default!\n"; } Foo(const Foo& foo) { std::cout << "Copy!\n"; } Foo(Foo&& foo) { std::cout << "Move!\n"; } };
#include <iostream>
struct Foo {
Foo() { std::cout << "Default!\n"; }
Foo(const Foo& foo) { std::cout << "Copy!\n"; }
Foo(Foo&& foo) { std::cout << "Move!\n"; }
};
struct Bar {
Foo foo;
Bar() {}
Bar(Bar &that) : foo(that.foo) {}
Bar(Bar &&that) : foo(std::move(that.foo)) {}
};
Bar f() {
Bar bar;
return bar;
}
int main() {
Bar bar(f());
}
但我得到的是:
Default!
Copy!
我看不出调用复制构造函数而不是移动构造函数的任何原因。如果我把关键字const
放在Bar的前面&在struct Bar的复制构造函数声明中,我得到了正确的结果。我知道在很多情况下,对于复制构造函数来说,采用const左值引用比仅采用左值引用更好,但我只想知道发生这种情况的原因
为什么在本例中,Bar&
优先于Bar&&
,即使f()
的返回值应被视为PR值?为什么关键字const
解决了这个问题?const
真的解决了这个问题吗?它是否与RVO(返回值优化)有关?或者,这只是一个编译器错误
我在Visual C++ 2012年11月CTP上测试了这个例子。p>
我在这里发现了一个类似的问题:
但我还是不明白为什么
有人能帮我吗?哇,当我用
Visual Studio在调试中看到“默认!复制!”
Visual Studio在发行版中我看到了“默认设置!”
如果将Bar(Bar&that)
更改为Bar(const Bar&that)
则“默认!移动!”
令人震惊的是,如果您将Bar(Bar&that)
的顺序切换为Bar(Bar&that)
(以便首先定义移动向量),那么您将实际看到“Default!move!”
你的问题可能已经回答了
临时对象无法绑定到非常量引用。复制构造函数必须引用const对象才能复制临时对象
另一件事是临时对象不可修改,因为它们很快就会被销毁。保持对临时变量的引用会导致对不存在对象的粗心修改。 这只是VisualC++中通常不遵守的,允许将非const LValk引用绑定到临时值。它违反了语言规则,但是它在被捕获之前已经过了很长时间,所以现在有一些依赖于错误的代码,如果错误被正确修复,这些代码将被破坏
该行为错误地允许使用非<代码> const 复制构造函数,结合VisualC++版本中的不完全的RoalRealStices支持,显然导致错误的过载被选中。
<>如果你想使用C++ 11/C++ 14的特性,你最好还是保持在最新的Visual C++版本之上。有了GCC,我就得到了Default代码>(工作中的正常NRVO),使用-fno elide构造函数
我得到了预期的默认值!移动快走代码>。可能是编译器b^hshortcomming?将Bar(Bar&that)
更改为Bar(const Bar&that)
@KerrekSB 1。我了解NRVO的情况。但是为什么只有两个而不是一个移动当复制省略设置为关闭时,是否需要代码>?2.你是说这只是我用过的编译器的一个bug?不管怎样,谢谢。@EmilioGaravaglia我在问题中已经提到了。我想知道的是为什么const
会产生如此大的差异。你为什么使用如此旧的版本?实际上,它没有任何优势——它没有发布,也从未获得生产代码许可,所以你甚至不能以工具链稳定性为借口。哇!我自己也测试了1、2和3,但4真的很令人惊讶!非常感谢。那么你知道为什么会发生这样的事情吗?好的,#4几乎可以肯定地确定这是一个编译器错误。公平地说,f()
应该返回std::move(bar)
@Mohammad不,不应该。事实上,这是一种悲观,因为它抑制了(N)RVO。这句话与所观察到的行为无关。@T.C.:这句话与它有关。复制构造函数不仅应该是更糟糕的匹配,它甚至不应该是候选集的一部分。@BenVoigt不确定,但这并不能解释任何事情。问题是“为什么叫它?”,而不是“为什么不叫它?”
Default!
Copy!