为什么用右值调用复制构造函数

问题描述

在下面的代码中,即使 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{}); 
}