C++ 使用std::move防止复制

C++ 使用std::move防止复制,c++,c++11,move-semantics,C++,C++11,Move Semantics,我有以下代码: #include <iostream> #include <vector> struct A { std::vector<int> x; A() { std::cout << "A()" << std::endl; } A(const A&) { std::cout << "A(const A&)" <

我有以下代码:

#include <iostream>
#include <vector>

struct A
{
    std::vector<int> x;

    A()
    {
        std::cout << "A()" << std::endl;
    }

    A(const A&)
    {
        std::cout << "A(const A&)" << std::endl;
    }

    ~A()
    {
        std::cout << "~A()" << std::endl;
    }
};

struct B : public A
{
    std::vector<int> y;

    B()
    {
        std::cout << "B()" << std::endl;
    }

    B(const A&a)
    {
        std::cout << "B(const A&)" << std::endl;
        x = std::move(a.x);
        y.resize(x.size());
    }

    B(const A&&a)
    {
        std::cout << "B(const A&&)" << std::endl;
        x = std::move(a.x);
        y.resize(x.size());
    }
    B(const B&)
    {
        std::cout << "B(const B&)" << std::endl;
    }

    ~B()
    {
        std::cout << "~B()" << std::endl;
    }
};

A ret_a()
{
    A a;
    a.x.resize(10);
    return a;
}

int main()
{
    std::cout << "section I" << std::endl << std::endl;

    A a = ret_a();  
    B b(a);
    std::cout << "a.x.size=" << a.x.size() << std::endl;

    std::cout << std::endl << "section II" << std::endl << std::endl;

    B b2(ret_a());
    std::cout << "b.x.size=" << b.x.size() << std::endl;

    std::cout << std::endl << "section III" << std::endl << std::endl;
    return 0;
}
  • 为什么“section I”中的a.x.size()的大小为10?我认为std::move应该将所有数据从a.x移动到y.x

  • 为什么“section II”调用构造函数A()两次?我认为B(const A&&)可以防止对A的过度复制

  • 更新

    参见固定代码

  • T&
    const T&
    不是同一类型。您几乎从不需要
    const
    rvalue引用-您无法窃取它的资源,因为您使它成为
    const
    <代码>x=标准::移动(a.x)B(常数A&A)中的code>复制
    A.x
    ,因为的返回类型是
    const vector&&
  • 构造函数
    B(const A&&
    调用
    A
    的默认构造函数,因为它派生自
    A
    ,并且成员初始值设定项列表不会尝试构造基
    A
    。这是第二个
    调用
    为什么
    a.x.size()
    在“第一节”中有10号尺寸?我认为
    std::move
    应该将所有数据从
    a.x
    移动到
    y.x

    这是因为
    B(常数A和&A)
    。由于
    a
    在该构造函数中是
    const
    ,因此您只能
    const
    访问其成员
    x
    ,并且对
    vector const
    调用
    std::move
    会导致
    vector const&&
    无法绑定到
    vector
    的move构造函数(它接受一个
    向量&&
    参数)。相反,它最终调用复制构造函数,而不修改源对象

    为什么“section II”调用构造函数
    A()
    两次?我认为
    B(const A&&)
    可以防止过度复制
    A

    第一个默认构造出现在
    ret_a()
    的主体中。第二个默认构造是
    B
    a
    子对象的构造。为了避免第二个
    移动
    成员初始值设定项列表中的
    a
    实例

    B(const A&&a)
    : A(std::move(a))
    {
        std::cout << "B(const A&&)" << std::endl;
        y.resize(x.size());
    }
    
    B(常数A和&A)
    :A(标准::移动(A))
    {
    标准::cout
    
    B(const A&&a)
    : A(std::move(a))
    {
        std::cout << "B(const A&&)" << std::endl;
        y.resize(x.size());
    }