C ++ Move构造函数(正确)是必需的,但从未运行

时间:2018-09-13 04:09:04

标签: c++11 constructor move move-semantics rvalue-reference

给出这个最小的例子:

#include <iostream>
#include  <stdexcept>

using std::cout;
using std::endl;
using std::runtime_error;

struct MyObj
{
    MyObj() { cout << "constructed\n";}
    MyObj(const MyObj& r) { cout << "copied\n"; }
    MyObj(MyObj&& r) noexcept { throw runtime_error("I should terminate the program if uncaught"); }// = delete;
};

void Test(MyObj value)
{
    cout << "called\n"; 
}

int main()
{
    Test(MyObj());

    return 0;
}

在这里,我(认为)实现了所有的构造函数,这些构造函数如果不存在的话,将由编译器实现。我也确认我可以让每个人执行给定的传统调用。我感到困惑的基础在于main的行为。

Test要求将传递给它的任何表达式(一旦求值)都可以用于构造MyObj的离散且独立的值。我通过了以前不存在的默认构造,应该产生一个r值引用&&

尝试从&&构造值是与已实现的move构造函数的完美匹配。 实际上,如果我声明构造函数已删除(= delete;),则编译器将失败,表示已删除引用的函数,表明我的推理至少在一定程度上是正确的。

但是,当我以代码示例中的代码声明该函数时,该实现注定要在执行时终止该程序...什么都不会发生。最初,我尝试使用cout来镜像其他构造函数,但没有任何反应,因此我在事前添加了runtime_error或anti。不过,编译器会警告声明为noexcept的函数肯定会抛出一个函数,但仍会编译并运行,并打印:

constructed
called

我还有两个问题。

  1. 为什么编译器为什么会失败,声称我引用了一个已删除的函数,如果该可执行文件显然不会调用它(在=delete;情况下)?

  2. 如果Test中的参数值既不通过复制也不移动,那么如何从r值引用中初始化?

注意:这是VS2017托管的MSVC 14.11.25503。

编辑:在给定noexcept的情况下,我只想澄清一下throw应该终止程序。

0 个答案:

没有答案