问题描述
在下面的代码中,即使 Line2 的 Account(20,"Dave") 是右值,为什么复制构造函数被称为 (Line1),而不是编译器抛出错误?正常函数接收右值的情况下,如果我们使用左值引用作为输入参数,编译器会抛出错误。
#include <iostream>
#include <string>
#include <vector>
class Account
{
private:
int num;
std::string name;
public:
Account(int lnum,std::string lname) : num {lnum},name {lname}
{
std::cout << "\n3arg constr";
}
Account(const Account &a) : Account{a.num,a.name} //Line1
{
std::cout << "\ncopy Constr";
}
};
int main()
{
std::vector<Account> myVec {};
myVec.push_back(Account(20,"Dave")); //Line2
std::cout << std::endl;
}
解决方法
是的,移动右值,复制左值。但是当没有相应的移动操作时,右值也会被复制。
编译器只会为没有定义任何自己的复制控制成员(复制构造函数、复制赋值或析构函数)的类合成移动构造函数,并且如果所有非{{1} } 成员可以移动。
如果一个类没有移动操作,就会使用对应的复制操作,通过正常的函数匹配(static
可以转换为T&&
)。
与复制操作不同,移动操作不会被隐式定义为删除函数。只是简单地使用副本。
至于const T&
。 Vector 提供了在 push_back()
过程中出现问题的保证,在没有 push_back()
类的移动构造函数的情况下,我们推送到的 vector
将保持不变,而是使用副本,
您在 Account(const Account &a)
中拥有的是 对 const 的左值引用。常量左值引用可以绑定到右值。引用reference(强调我的)
右值引用可用于延长临时的生命周期 对象(注意,对 const 的左值引用可以延长 临时对象也是如此,但它们不能通过它们进行修改):
struct Foo{};
void bar(Foo && f) {}
void baz(Foo const&) {}
void qux(Foo&) {}
int main() {
bar(Foo{}); //rvalue reference binds to rvalue
baz(Foo{}); //const rvalue reference binds to rvalue
//Error: cannot bind non-const lvalue reference of type 'Foo&' to an rvalue of type 'Foo'
// qux(Foo{});
}