为什么移动的 class 对象在绑定到函数参数时不触发移动构造函数?
Why does a moved class object not trigger the move constructor when bound to function parameter?
假设
- 我有一个重要的 class 对象
A
,它定义了一个复制和移动构造函数
- 我将此对象移动到一个接受
A
或 A&&
的函数
现在,如果 foo
的参数类型为 A
,则调用移动构造函数(这是预期的,因为 A&&
作为参数传递给函数-本地 A).
但是在A&&
的情况下,没有调用移动构造函数,实际上没有调用构造函数。为什么?
我原以为这是由于复制省略而发生的,但它也发生在为 gcc 设置了 -O0 标志的情况下。我还认为 && 基本上只是 flags
参数列表中用于重载决策的右值,因为在函数体内,它被视为左值。但这意味着左值 A
将绑定移动的 A&&
并且应该再次调用移动构造函数。我错过了什么?
在 x86-x64 gcc 11.2 下编译
#include <iostream>
#include <string>
#include <string.h>
struct A
{
char * str_;
A() {
std::cout << "normal constructor called\n";
str_ = new char[7];
sprintf(str_, "Hello!");
}
~A(){ delete[] str_; }
A(A& copy) {
std::cout << "copy constructor called\n";
str_ = strdup(copy.str_);
}
A(A&& moved) {
std::cout << "move constructor called\n";
str_ = moved.str_;
moved.str_ = nullptr;
}
};
void foo(A&& a)
{
std::cout << a.str_ << "\n";
}
int main()
{
A obj;
foo(std::move(obj));
}
当 foo
采用 A&&
时,您将绑定到 r-value 引用,而不是创建任何需要构造的新 A
对象。
这是因为 std::move
基本上只是对 r-value 引用的转换。
当 foo
采用 A
时,您将 r-value 引用传递给 A
作为构造 A
的一种方式。在这里,选择移动构造函数,因为它以 A&&
作为参数。
假设
- 我有一个重要的 class 对象
A
,它定义了一个复制和移动构造函数 - 我将此对象移动到一个接受
A
或A&&
的函数
现在,如果 foo
的参数类型为 A
,则调用移动构造函数(这是预期的,因为 A&&
作为参数传递给函数-本地 A).
但是在A&&
的情况下,没有调用移动构造函数,实际上没有调用构造函数。为什么?
我原以为这是由于复制省略而发生的,但它也发生在为 gcc 设置了 -O0 标志的情况下。我还认为 && 基本上只是 flags
参数列表中用于重载决策的右值,因为在函数体内,它被视为左值。但这意味着左值 A
将绑定移动的 A&&
并且应该再次调用移动构造函数。我错过了什么?
在 x86-x64 gcc 11.2 下编译
#include <iostream>
#include <string>
#include <string.h>
struct A
{
char * str_;
A() {
std::cout << "normal constructor called\n";
str_ = new char[7];
sprintf(str_, "Hello!");
}
~A(){ delete[] str_; }
A(A& copy) {
std::cout << "copy constructor called\n";
str_ = strdup(copy.str_);
}
A(A&& moved) {
std::cout << "move constructor called\n";
str_ = moved.str_;
moved.str_ = nullptr;
}
};
void foo(A&& a)
{
std::cout << a.str_ << "\n";
}
int main()
{
A obj;
foo(std::move(obj));
}
当 foo
采用 A&&
时,您将绑定到 r-value 引用,而不是创建任何需要构造的新 A
对象。
这是因为 std::move
基本上只是对 r-value 引用的转换。
当 foo
采用 A
时,您将 r-value 引用传递给 A
作为构造 A
的一种方式。在这里,选择移动构造函数,因为它以 A&&
作为参数。