Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/132.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++ 删除移动构造函数时,为什么不复制我的对象?_C++_C++11 - Fatal编程技术网

C++ 删除移动构造函数时,为什么不复制我的对象?

C++ 删除移动构造函数时,为什么不复制我的对象?,c++,c++11,C++,C++11,我试图用这段代码来演示复制构造函数的使用。我的假设是,当我有一个按值返回的函数时,默认情况下,我的编译器将执行对象的移动。但是当move构造函数不可用时,编译器将进行复制(在C++03中,编译器将在按值返回时进行复制)。那么,为什么在下面的示例中,编译器尝试调用显式删除的move构造函数而不是可用的copy构造函数呢?我在GCC4.7.2中编译这个 struct S { S() = default; S(S const &) = default; S(S&

我试图用这段代码来演示复制构造函数的使用。我的假设是,当我有一个按值返回的函数时,默认情况下,我的编译器将执行对象的移动。但是当move构造函数不可用时,编译器将进行复制(在C++03中,编译器将在按值返回时进行复制)。那么,为什么在下面的示例中,编译器尝试调用显式删除的move构造函数而不是可用的copy构造函数呢?我在GCC4.7.2中编译这个

struct S
{
    S() = default;
    S(S const &) = default;
    S(S&&) = delete;
};

S f() { return S{}; }

int main()
{
    f();
}
prog.cpp:在函数
的f()中

程序cpp:8:18:错误:使用已删除的函数
'S::S(S&&)

程序cpp:5:5:错误:在此处声明


删除的移动成员是邪恶的。它们不是非法的,因为总有一天,有人会发现它们的巧妙用途。但我还没看到它有什么用处

删除特殊成员与没有特殊成员不是一回事。这一点在move构造函数和move赋值运算符中最为明显

存在时,无论是删除的、默认的还是用户定义的,移动构造函数和移动分配操作符都参与重载解析。这意味着他们与特殊副本成员“竞争”。复制成员通常倾向于常量左值,而移动成员则吸引右值

从函数返回局部类型时(当局部类型与返回类型是同一个非cv限定类型时),return语句首先将返回表达式视为右值,只有当它找不到合适的构造函数时,才会将其视为左值。即,匹配适当的构造函数以从函数返回本地对象是一个两阶段操作

如果您根本没有move构造函数(甚至没有删除),但是您有一个普通的copy构造函数(采用常量&),那么return语句中的rvalue将与copy构造函数匹配

当您有一个移动构造函数时,即使它被标记为deleted,return语句中的右值也会发现移动构造函数比复制构造函数更匹配

摘要

除非你真的知道自己在做什么,永远不要删除移动成员。如果您不希望您的类型是可移动的,只需不定义移动成员并确保您声明了复制成员,即使复制成员是
=default
'd

更新


我想很难引用标准中删除的内容 不行吗?——DyP

8.4.3删除的定义[dcl.fct.def.delete]

2隐式引用已删除函数的程序,或 明确地说,除了声明它,它是格式错误的。[注:此 包括隐式或显式调用函数并形成 指向函数成员的指针或指针。它甚至适用于 表达式中可能未计算的引用。如果 函数重载,仅当函数为 通过过载分辨率选择。-结束注释]

更新2

12.8复制和移动类对象[class.copy]

9如果类X的定义没有显式声明移动 构造函数,则仅当且仅当 如果

  • X没有用户声明的复制构造函数
  • X没有用户声明的复制分配运算符
  • X没有用户声明的移动分配运算符,并且
  • X没有用户声明的析构函数
[注意:当移动构造函数未隐式声明或 显式提供的表达式,否则将调用 移动构造函数可以调用复制构造函数。-结束说明]


删除的移动成员是邪恶的。它们不是非法的,因为总有一天,有人会发现它们的巧妙用途。但我还没看到它有什么用处

删除特殊成员与没有特殊成员不是一回事。这一点在move构造函数和move赋值运算符中最为明显

存在时,无论是删除的、默认的还是用户定义的,移动构造函数和移动分配操作符都参与重载解析。这意味着他们与特殊副本成员“竞争”。复制成员通常倾向于常量左值,而移动成员则吸引右值

从函数返回局部类型时(当局部类型与返回类型是同一个非cv限定类型时),return语句首先将返回表达式视为右值,只有当它找不到合适的构造函数时,才会将其视为左值。即,匹配适当的构造函数以从函数返回本地对象是一个两阶段操作

如果您根本没有move构造函数(甚至没有删除),但是您有一个普通的copy构造函数(采用常量&),那么return语句中的rvalue将与copy构造函数匹配

当您有一个移动构造函数时,即使它被标记为deleted,return语句中的右值也会发现移动构造函数比复制构造函数更匹配

摘要

除非你真的知道自己在做什么,永远不要删除移动成员。如果您不希望您的类型是可移动的,只需不定义移动成员并确保您声明了复制成员,即使复制成员是
=default
'd

更新


我想很难引用标准中删除的内容 不行吗?——DyP

8.4.3删除的定义[dcl.fct.def.delete]

2隐式引用已删除函数的程序,或 明确地说,除了声明它,它是不可能的