【问题标题】:Why is Copy constructor called with rvalue为什么用右值调用复制构造函数
【发布时间】:2021-06-26 07:05:42
【问题描述】:

在下面的代码中,尽管 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;
}

【问题讨论】:

  • 由于Account 没有定义移动ctor (?)。
  • 一个 lvalue-reference-to-const 可以绑定到 rvalues。
  • "在普通函数接收右值的情况下,如果我们使用左值引用作为输入参数,编译器会抛出错误。" -- 你能举个例子吗?据我所知,右值可以绑定到普通函数和构造函数中的const左值引用。 (没有const,在普通函数和构造函数中都会出现错误。)
  • 您对下面提供的答案有任何疑问或问题吗?

标签: c++ copy-constructor move-constructor


【解决方案1】:

是的,右值被移动,左值被复制。但是当没有相应的移动操作时,右值也会被复制

编译器只会为没有定义任何自己的复制控制成员(复制构造函数、复制赋值或析构函数)的类合成一个移动构造函数,如果所有非static成员可以移动。

如果一个类没有移动操作,则会使用对应的复制操作,通过正常的函数匹配(T&amp;&amp;可以转换为const T&amp;)。

与复制操作不同,移动操作不会被隐式定义为删除函数。只是简单地使用副本。

至于push_back()。 Vector 保证在push_back() 的过程中出现问题,我们推送的vector 将保持不变,在没有noexcept 移动类的构造函数的情况下,使用副本代替,

【讨论】:

    【解决方案2】:

    Account(const Account &amp;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{}); 
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-05-14
      • 2018-01-20
      • 2021-02-18
      • 2014-01-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多