C++11:'decltype class instance declaration' 与 std::move( ) 不调用 'move constructor.' 为什么?
C++11: 'decltype class instance declaration' with std::move( ) doesn't call 'move constructor.' Why?
我最近开始使用 c++ 并且我选择学习 c++11 特性。
但是 c++ 代码如何 运行 有时并不那么具体。
下面是我的代码。
在带有 decltype(std::move(sample)) sample2 = std::move(sample);
的部分,我不确定为什么这一行不调用移动构造函数。
你能解释一下为什么吗?
#include <iostream>
class AAA
{
public:
AAA() { std::cout << "default constructor" << std::endl; }
AAA(const AAA& cs) { std::cout << "copy constructor" << std::endl; }
AAA(AAA&& cs) { std::cout << "move constructor" << std::endl; }
~AAA() { std::cout << "destructor" << std::endl; }
};
int main(int argc, char* args[])
{
AAA sample;
// ((right here))
decltype(std::move(sample)) sample2 = std::move(sample);
return 0;
}
它是在 [ubuntu 16.04 LTS] 上用 [gcc 5.4.0]
编译的
您的代码段扩展为
AAA&& sample2 = std::move(sample);
将右值(std::move(sample)
的结果)绑定到右值引用 (sample2
)。没有构造新对象,因此没有调用这样的构造函数。
函数 std::move<T>
return 是 T &&
,所以对于 std::move(sample)
它 return 是 AAA &&
。这是一个 rvalue reference and behave a lot like an lvalue reference(像 AAA &
这样的类型将是一个左值引用),因为它们都是已经存在的对象的别名。
重要的是要了解 std::move
而不是 本身会导致任何东西被移动。它只是 returns 对给定参数的右值引用。例如 std::move(foo);
单独做任何事情。只有当结果用于初始化或分配给对象时,它才有用。
例如 auto bar = std::move(foo);
将 return 对 foo
的右值引用,并使用该引用调用 bar
的构造函数。
回答这个问题,因为std::move(sample)
return是一个AAA &&
,有问题的那一行和AAA && sample2 = std::move(sample);
是一样的。该行为实际上与 AAA & sample2 = sample;
相同。在这两种情况下,您都在初始化对现有对象的引用,并且不需要构造新对象。
如果您的目标是将 sample
移动到新的 AAA
,正确的行应该是 auto sample2 = std::move(sample);
,就像您对 sample3
所做的一样。尽管要注意行 sample3
是从已经移动的 sample
.
我最近开始使用 c++ 并且我选择学习 c++11 特性。 但是 c++ 代码如何 运行 有时并不那么具体。
下面是我的代码。
在带有 decltype(std::move(sample)) sample2 = std::move(sample);
的部分,我不确定为什么这一行不调用移动构造函数。
你能解释一下为什么吗?
#include <iostream>
class AAA
{
public:
AAA() { std::cout << "default constructor" << std::endl; }
AAA(const AAA& cs) { std::cout << "copy constructor" << std::endl; }
AAA(AAA&& cs) { std::cout << "move constructor" << std::endl; }
~AAA() { std::cout << "destructor" << std::endl; }
};
int main(int argc, char* args[])
{
AAA sample;
// ((right here))
decltype(std::move(sample)) sample2 = std::move(sample);
return 0;
}
它是在 [ubuntu 16.04 LTS] 上用 [gcc 5.4.0]
编译的您的代码段扩展为
AAA&& sample2 = std::move(sample);
将右值(std::move(sample)
的结果)绑定到右值引用 (sample2
)。没有构造新对象,因此没有调用这样的构造函数。
函数 std::move<T>
return 是 T &&
,所以对于 std::move(sample)
它 return 是 AAA &&
。这是一个 rvalue reference and behave a lot like an lvalue reference(像 AAA &
这样的类型将是一个左值引用),因为它们都是已经存在的对象的别名。
重要的是要了解 std::move
而不是 本身会导致任何东西被移动。它只是 returns 对给定参数的右值引用。例如 std::move(foo);
单独做任何事情。只有当结果用于初始化或分配给对象时,它才有用。
例如 auto bar = std::move(foo);
将 return 对 foo
的右值引用,并使用该引用调用 bar
的构造函数。
回答这个问题,因为std::move(sample)
return是一个AAA &&
,有问题的那一行和AAA && sample2 = std::move(sample);
是一样的。该行为实际上与 AAA & sample2 = sample;
相同。在这两种情况下,您都在初始化对现有对象的引用,并且不需要构造新对象。
如果您的目标是将 sample
移动到新的 AAA
,正确的行应该是 auto sample2 = std::move(sample);
,就像您对 sample3
所做的一样。尽管要注意行 sample3
是从已经移动的 sample
.