如何解决调用std :: move而不移动构造函数或移动分配
我们知道std :: move does not actually move anything。只是将左值引用(&)转换为右值引用(&&)。
然后在以下示例中,如何调用复制构造函数?如果没有移动构造函数,那么使用std :: move()构造对象的方式又如何依赖于复制构造函数?究竟如何与变量b
进行绑定?
struct Test {
// Default constructor
Test() {
std::cout << "Constructor is called." << std::endl;
mValue = 0;
}
// Copy constructor
Test(const Test& rhs) {
std::cout << "Copy Constructor is called." << std::endl;
mName = rhs.mName;
mValue = rhs.mValue;
}
std::string mName;
int mValue;
};
int main() {
Test a;
Test b = std::move(a);
return 0;
}
输出:
Constructor is called.
Copy Constructor is called.
解决方法
以类推为理由。考虑一下这段代码:
void doSomething(const int& x) {
std::cout << "You like " << x << "? That's my favorite number!" << std::endl;
}
int main() {
doSomething(137); // <-- Here
}
现在,重点关注main
中的通话。这段代码可以编译并正常运行,但是有些奇怪。请注意,doSomething
接受了const int&
。这意味着它接受int
的引用,并且引用(通常)仅绑定到左值。但是这里的参数137是右值。有什么作用?
之所以可行,是因为C ++语言特别允许const
左值引用绑定到右值,即使常规左值引用不能。例如:
const int& totallyLegal = 137; // Yep,that's fine!
int& whoaNotCoolMan = 42; // Compile error!
您可以这样做有两个原因。如果您有一个const
左值引用,则已保证可以查看所引用的对象,但不能对其进行修改。因此,将左值引用绑定到右值是安全的,因为那样您将无法获取“纯值”并为其分配某些内容。从历史上看,在C ++ 11之前的版本中,当不存在右值引用时,这使得可以编写使用“请以不涉及复制的方式将此参数传递给我”的函数,方法是使用{ {1}}左值参考。
现在我们有了左值引用,此规则引入了一些以前没有的混淆点。特别是,const
可以绑定到任何类型为const T&
的表达式的结果,即使它是T
或T&
。这就是在您的情况下选择复制构造函数的原因。
不过,这里还有另一个细微差别。如果您自己不这样做,则C ++编译器会为类自动定义默认构造函数,复制构造函数和赋值运算符的方式相同,C ++编译器也可以自动定义移动构造函数。但是,有一条规则说,如果类型具有用户定义的副本构造函数,则编译器不会为您生成move构造函数。因此,对您的问题的完整答案是:“复制构造函数的存在意味着未定义move构造函数,并且由于复制构造函数接受T&&
左值引用,因此它将绑定到右值和左值。”
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。