Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/cplusplus11/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++11 为什么调用复制构造函数而不是移动构造函数?_C++11_Copy Constructor_Move Semantics_Rvalue Reference_Rvo - Fatal编程技术网

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!