简体   繁体   English

为什么编译器使用move构造函数而不是copy构造函数

[英]Why does compiler use move constructor instead of the copy constructor

Is it ok that the following code 下面的代码可以吗

#include <iostream>

struct Foo
{
    Foo() { std::cout << "Foo::Foo" << std::endl; }
    ~Foo() { std::cout << "Foo::~Foo" << std::endl; }

    Foo(const Foo&) { std::cout << "Foo::Foo(const Foo&)" << std::endl; }
    Foo& operator=(const Foo&) { std::cout << "Foo::operator=(const Foo&)" << std::endl; return *this; }

    Foo(Foo&&) { std::cout << "Foo::Foo(Foo&&)" << std::endl; }
    Foo& operator=(Foo&&) { std::cout << "Foo::operator=(Foo&&)" << std::endl; return *this; }
};

Foo foo()
{
    Foo second;
    return second;
}

int main()
{
    foo();
}

produces such output: 产生这样的输出:

Foo::Foo
Foo::Foo(Foo&&)
Foo::~Foo
Foo::~Foo

Why does it call move constructor instead of the copy constructor? 为什么调用移动构造函数而不是复制构造函数?

The answer is simply because the standard says so. 答案仅仅是因为该标准是这样说的。 Section 12.8, paragraph 32: 第12.8节第32段:

When the criteria for elision of a copy/move operation are met, but not for an exception-declaration, and the object to be copied is designated by an lvalue, or when the expression in a return statement is a (possibly parenthesized) id-expression that names an object with automatic storage duration declared in the body or parameter-declaration-clause of the innermost enclosing function or lambda-expression, overload resolution to select the constructor for the copy is first performed as if the object were designated by an rvalue. 当满足复制/移动操作的省略标准,但不满足异常声明的标准,并且要复制的对象由左值指定时,或者当return语句中的表达式为(可能带有括号)id-用最内层封闭函数或lambda-expression的主体或参数声明子句声明的具有自动存储持续时间的对象的表达式,首先执行重载解析以选择副本的构造函数,就好像该对象由右值指定。

And that's basically all there is to it. 基本上就是全部。 Logically, if the variable has automatic storage duration, and you return it, then immediately after the return, the variable will not exist any more when the local scope cleans up. 从逻辑上讲,如果该变量具有自动存储期限,并且您returnreturn ,则在返回后立即在清理本地作用域时不再存在该变量。 That is why, even though it is an lvalue, it is quite similar to an rvalue. 这就是为什么即使它是一个左值,它也非常类似于一个右值。 Because it's still technically an lvalue, this exception has to be made explicitly in the standard, and here we are. 因为从技术上讲它仍然是左值,所以必须在标准中明确地指定此异常,在这里就可以了。 Note that this whole situation is specific to return ing from a function, and does not include scope ending in general. 请注意,这整个情况特定于从函数return ,并且一般不包括范围结尾。

second is returned from foo , and, being a local object, is treated as an rvalue (thanks to Nir Friedman for the correct explanation ). second是从foo返回的,并且作为本地对象被视为右值(感谢Nir Friedman的正确解释 )。 The returned Foo object is constructed from a temporary, which binds to the move constructor. 返回的Foo对象是从临时对象构造的,该临时对象绑定到move构造函数。

Modern compiler should skip the move constructor call and use copy elision ( demo ). 现代编译器应跳过move构造函数调用,并使用复制省略( demo )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么调用移动构造函数而不是复制构造函数 - Why move constructor is called instead of copy constructor 为什么调用复制构造函数而不是移动构造函数? - Why is the copy constructor called instead of the move constructor? 复制构造函数被调用,而不是移动构造函数-为什么? - Copy constructor is called instead of move constructor - why? 为什么这会调用复制构造函数,而不是移动构造函数? - Why does this call the copy constructor, not the move constructor? 模板“复制构造函数”不会阻止编译器生成的移动构造函数 - Template “copy constructor” does not prevent compiler-generated move constructor 为什么使用移动构造函数而不是复制? - why move constructor being used instead of copy? 为什么在返回时调用复制构造函数而不是移动构造函数? - Why is the copy constructor called instead of the move constructor when returning? 为什么调用复制构造函数而不是使用右值初始值设定项的移动构造函数? - Why copy constructor is called instead of move constructor with an rvalue initializer? 强制使用复制构造函数而不是move构造函数 - Forcing the copy constructor instead of the move constructor 程序使用复制构造函数而不是移动构造函数 - Program uses Copy Constructor instead of Move Constructor
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM