gpt4 book ai didi

c++ - 为什么删除移动构造函数时我的对象没有被复制?

转载 作者:IT老高 更新时间:2023-10-28 12:41:33 25 4
gpt4 key购买 nike

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

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

S f() { return S{}; }

int main()
{
f();
}

prog.cpp: In function ‘S f()’:
prog.cpp:8:18: error: use of deleted function ‘S::S(S&&)’
prog.cpp:5:5: error: declared here

最佳答案

删除的招式成员是邪恶的。它们并没有被取缔,因为有一天,有人会为它们找到一个聪明的用途。不过还没看到好用的。

删除特殊成员与没有特殊成员不同。没有什么比使用移动构造函数和移动赋值运算符更明显了。

当存在时,无论是删除的、默认的还是用户定义的,移动构造函数和移动赋值运算符都参与重载决议。这意味着他们与特殊拷贝成员“竞争”。复制成员通常会偏爱 const 左值,而移动成员会吸引右值。

当从函数返回局部类型时(当局部类型与返回类型是相同的 un-cv-qualified 类型时),return 语句首先将返回表达式视为右值,并且仅当它不能找到一个合适的构造函数,然后将其视为左值。 IE。匹配从函数返回本地对象的正确构造函数是一个两阶段操作。

如果你根本没有移动构造函数(甚至没有删除),但你有一个普通的复制构造函数(接受一个 const &),那么 return 语句中的右值将匹配复制构造函数。

当你确实有移动构造函数时,即使它被标记为已删除,return 语句中的右值也会发现移动构造函数比复制构造函数更匹配。

总结

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

更新

I suppose it's hard to provide quotes from the Standard on what delete doesn't do? – DyP

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

2 A program that refers to a deleted function implicitly or explicitly, other than to declare it, is ill-formed. [ Note: This includes calling the function implicitly or explicitly and forming a pointer or pointer-to-member to the function. It applies even for references in expressions that are not potentially-evaluated. If a function is overloaded, it is referenced only if the function is selected by overload resolution. — end note ]

更新 2

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

9 If the definition of a class X does not explicitly declare a move constructor, one will be implicitly declared as defaulted if and only if

  • X does not have a user-declared copy constructor,
  • X does not have a user-declared copy assignment operator,
  • X does not have a user-declared move assignment operator, and
  • X does not have a user-declared destructor.

[Note: When the move constructor is not implicitly declared or explicitly supplied, expressions that otherwise would have invoked the move constructor may instead invoke a copy constructor. — end note ]

关于c++ - 为什么删除移动构造函数时我的对象没有被复制?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16703798/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com