简体   繁体   English

使用std :: move以防止复制

[英]using std::move to prevent copying

I have the following code: 我有以下代码:

#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;
}

With output (VS2013, Release build) 带输出(VS2013,发布版本)

section I

A()
A()
B(const A&)
a.x.size=10

section II

A()
A()
B(const A&&)
~A()
b.x.size=10

section III

~B()
~A()
~B()
~A()
~A()
  1. Why axsize() within "section I" has size 10? 为什么“ I部分”中的axsize()的大小为10? I thought that std::move should move all data from ax to yx 我认为std :: move应该将所有数据从ax移到yx

  2. Why did "section II" call constructor A() twice? 为什么“第二节”两次调用构造函数A()? I thought that B(const A&&) would prevent excessive copying of A 我认为B(const A &&)可以防止A的过度复制

UPDATE UPDATE

see fixed code at http://pastebin.com/70Nmt9sT 请参阅http://pastebin.com/70Nmt9sT上的固定代码

  1. T&& and const T&& are not the same type. T&&const T&&不是同一类型。 You almost never want a const rvalue reference - you can't steal its resources since you made it const ! 您几乎永远不需要const rvalue引用-自从将其const后就无法窃取其资源! x = std::move(ax); in B(const A&a) copies ax since the return type of std::move(ax) is const vector<int>&& . B(const A&a) const vector<int>&&复制ax因为std::move(ax)的返回类型是const vector<int>&&
  2. The constructor, B(const A&&) calls the default constructor of A since it is derived from A , and the member initializer list does not make an attempt to construct the base A . 构造函数, B(const A&&)调用的默认构造A因为它是衍生自A ,和成员初始化列表不会使试图构造基A This is the second A call. 这是第二个A呼叫。

Why axsize() within "section I" has size 10? 为什么“ I部分”中的axsize()大小为10? I thought that std::move should move all data from ax to yx 我认为std::move应该将所有数据从ax移到yx

This is because of B(const A&& a) . 这是因为B(const A&& a) Since a is const within that constructor, you only have const access to its member x , and calling std::move on a vector<T> const results in a vector<T> const&& which cannot bind to vector 's move constructor (which takes a vector<T>&& argument). 由于a是该构造const ,因此您只能对其成员x进行const访问,并且在vector<T> const上调用std::move导致vector<T> const&&不能绑定到vector的move构造函数(采用vector<T>&&参数)。 Instead it ends up calling the copy constructor, which leaves the source object unmodified. 相反,它最终调用了复制构造函数,这使源对象保持不变。

Why did "section II" call constructor A() twice? 为什么“第二节”两次调用构造函数A() I thought that B(const A&&) would prevent excessive copying of A 我认为B(const A&&)可以防止A过度复制

The first default construction occurs within the body of ret_a() . 第一个默认构造发生在ret_a()的主体内。 The second default construction is that of the A sub-object of B . 第二种默认构造是BA子对象的构造。 To avoid the second one move the A instance in the member initializer list. 为了避免第二步,在成员初始化器列表中move A实例。

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

Note that the move doesn't actually result in moving the contents of a due to the same reason as explained above. 需要注意的是, move实际上并没有导致的内容移动a因同样的原因如上所述。 Moreover, even modifying the signature to B(A&& a) would not result in the contents of a being moved because the user provided copy constructor and destructor definitions prevent implicit generation of a move constructor for A , and it'll be copied instead. 此外,即使修改签名B(A&& a)不会导致内容a移动由于用户提供拷贝构造函数和析构函数的定义,防止转移构造的隐代A ,它会被复制而不是。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM