取消引用新对象时移动语义和构造函数
Move semantics and constructors when dereferencing a new
我有以下代码 (http://coliru.stacked-crooked.com/a/a0e5ff6ee73634ee):
#include <iostream
class A {
public:
explicit A(int a) {std::cout << "Main constructor" << std::endl;}
A(const A& a) {std::cout << "Copy constructor" << std::endl;}
A& operator =(const A& a) {std::cout << "Copy assignment" << std::endl; return *this;}
A(A&& a) {std::cout << "Move constructor" << std::endl;}
A& operator =(A&& a) {std::cout << "Move assignemnt" << std::endl; return *this;}
};
int main(void) {
std::cout << "\nA a3(A(0))" << std::endl;
A a3(A(0));
std::cout << "\nA a31(std::move(A(0)))" << std::endl;
A a31(std::move(A(0)));
std::cout << "\nA a4(*(new A(0)))" << std::endl;
A a4(*(new A(0)));
std::cout << "\nA a41(std::move(*(new A(0))))" << std::endl;
A a41(std::move(*(new A(0))));
}
这段代码写了以下内容:
A a3(A(0))
Main constructor
-> 阅读 Move semantics and copy constructor 后,我假设发生了 RVO 并且 a3 接管了 A(0) 的构造内容。
A a31(std::move(A(0)))
Main constructor
Move constructor
-> 确定
A a4(*(new A(0)))
Main constructor
Copy constructor
-> 为什么这不是移动构造函数而不是复制构造函数?
A a41(std::move(*(new A(0))))
Main constructor
Move constructor
-> 确定
编辑:
在更深入地分析问题之后,我意识到实际上 @sameerkn 是对的。然而,正如@Angew 建议的那样,我试图分析静态变量发生了什么:这些变量并没有像人们预期的那样移动(它们似乎被视为 const 变量)。
在这里查看完整代码:
http://melpon.org/wandbox/permlink/RCntHB9dcefv93ID
以下代码:
A a1(testStatic(1));
A a2(std::move(*(a1.getPointer()))); <-- Moving a dereference
std::cout << "\na1.mValue = " << a1.mValue << std::endl;
std::cout << "a2.mValue = " << a2.mValue << std::endl;
会 return:
Main constructor: This is my long String that should not be SSOed [STATIC]
Copy constructor: This is my long String that should not be SSOed [STATIC]
return aLocal
Move constructor <-- The dereferenced pointer is moved as expected
Destructor: [mValue moved away] <-- See here that the string was moved away
Move constructor <-- Moved again because of std::move
A a4(*(new A(0)))
Main constructor
Copy constructor
-> Why is not this a move constructor instead of the Copy constructor ?
因为取消引用指针会给出左值引用。指针本身是右值这一事实没有任何作用——为什么要这样呢?您可以很容易地让右值指针指向绝对不是右值的东西。示例:
std::string s{"42"};
std::string* getPointer()
{
return &s;
}
int main()
{
std::string x(*getPointer());
std::cout << s;
}
getPointer
返回的指针是一个右值,就像new A
返回的指针一样。但是您肯定不会期望代码将s
的内容移动到x
,对吗?
new A(0);
正在通过 "new" 创建一个对象。 (注意:它创建了一个纯对象,该对象具有一个标识,该标识可以由代码中 "new" 返回的地址标识,并且该对象可用于代码以供其使用,绝不是一个临时的无名对象。 )
并将语义工作转移到其身份不可利用的纯临时对象上。
我有以下代码 (http://coliru.stacked-crooked.com/a/a0e5ff6ee73634ee):
#include <iostream
class A {
public:
explicit A(int a) {std::cout << "Main constructor" << std::endl;}
A(const A& a) {std::cout << "Copy constructor" << std::endl;}
A& operator =(const A& a) {std::cout << "Copy assignment" << std::endl; return *this;}
A(A&& a) {std::cout << "Move constructor" << std::endl;}
A& operator =(A&& a) {std::cout << "Move assignemnt" << std::endl; return *this;}
};
int main(void) {
std::cout << "\nA a3(A(0))" << std::endl;
A a3(A(0));
std::cout << "\nA a31(std::move(A(0)))" << std::endl;
A a31(std::move(A(0)));
std::cout << "\nA a4(*(new A(0)))" << std::endl;
A a4(*(new A(0)));
std::cout << "\nA a41(std::move(*(new A(0))))" << std::endl;
A a41(std::move(*(new A(0))));
}
这段代码写了以下内容:
A a3(A(0))
Main constructor
-> 阅读 Move semantics and copy constructor 后,我假设发生了 RVO 并且 a3 接管了 A(0) 的构造内容。
A a31(std::move(A(0)))
Main constructor
Move constructor
-> 确定
A a4(*(new A(0)))
Main constructor
Copy constructor
-> 为什么这不是移动构造函数而不是复制构造函数?
A a41(std::move(*(new A(0))))
Main constructor
Move constructor
-> 确定
编辑:
在更深入地分析问题之后,我意识到实际上 @sameerkn 是对的。然而,正如@Angew 建议的那样,我试图分析静态变量发生了什么:这些变量并没有像人们预期的那样移动(它们似乎被视为 const 变量)。
在这里查看完整代码:
http://melpon.org/wandbox/permlink/RCntHB9dcefv93ID
以下代码:
A a1(testStatic(1));
A a2(std::move(*(a1.getPointer()))); <-- Moving a dereference
std::cout << "\na1.mValue = " << a1.mValue << std::endl;
std::cout << "a2.mValue = " << a2.mValue << std::endl;
会 return:
Main constructor: This is my long String that should not be SSOed [STATIC]
Copy constructor: This is my long String that should not be SSOed [STATIC]
return aLocal
Move constructor <-- The dereferenced pointer is moved as expected
Destructor: [mValue moved away] <-- See here that the string was moved away
Move constructor <-- Moved again because of std::move
A a4(*(new A(0))) Main constructor Copy constructor
-> Why is not this a move constructor instead of the Copy constructor ?
因为取消引用指针会给出左值引用。指针本身是右值这一事实没有任何作用——为什么要这样呢?您可以很容易地让右值指针指向绝对不是右值的东西。示例:
std::string s{"42"};
std::string* getPointer()
{
return &s;
}
int main()
{
std::string x(*getPointer());
std::cout << s;
}
getPointer
返回的指针是一个右值,就像new A
返回的指针一样。但是您肯定不会期望代码将s
的内容移动到x
,对吗?
new A(0);
正在通过 "new" 创建一个对象。 (注意:它创建了一个纯对象,该对象具有一个标识,该标识可以由代码中 "new" 返回的地址标识,并且该对象可用于代码以供其使用,绝不是一个临时的无名对象。 )
并将语义工作转移到其身份不可利用的纯临时对象上。