如何减少c ++中的副本

时间:2015-08-22 04:30:45

标签: c++

我正在编写一个Bytearray类,并希望实现一个成员函数copy(int start, int end),它可以复制一段数据并返回一个新的Bytearray对象。我的实现是

Bytearray Bytearray::copy(int start, int end){
    Bytearray b(end - start);
    for(int i = start; i < end; i++){
        b._data[i-start] = _data[i];
    }
    return b;
}

但据我所知,如果我拨打Bytearray aa = bb.copy(1, 5);,则需要3次复制数据。一个是从this到临时对象b的复制数据。然后它调用复制构造函数和operator =。如何减少复制并提高效率。

3 个答案:

答案 0 :(得分:3)

您的功能根本不会调用Bytearray::operator=()。调用者可能在表达式x = a.copy(start, end)中。

在实践中,大多数现代编译器都会偏离临时工,尽管 - 严格来说 - 标准并不要求他们这样做。

使用C ++ 11,您可以提供一个移动构造函数,这将更加明确地鼓励编译器消除临时性。没有它(例如你没有在C ++ 11中提供移动构造函数,或者你使用的是前C ++ 11编译器),典型的方法是通过引用传递目标对象

void Bytearray::copy(int start, int end, Bytearray& b)
{
   for(int i = start; i < end; i++){
      b._data[i-start] = _data[i];
}

或指针

void Bytearray::copy(int start, int end, Bytearray* b)
{
    // assume b is the address of a valid object
    for(int i = start; i < end; i++){
        b->_data[i-start] = _data[i];
}

答案 1 :(得分:0)

您应该实现移动构造函数并移动赋值。它将允许编译器移动数据而不是复制它。它基本上是这样的:

Bytearray Bytearray::copy(size_t start, size_t end) {
    Bytearray b; // declare as usual

    return move(b); // the return value is constructed by move
}

// how to use it?
// use it as usual!
// myB is constructed by move.
Bytearray myB = otherB.copy();

如何实现?这很容易。它就像一个复制构造函数,但你窃取数据而不是复制它。

struct Bytearray {
    Data* _data = nullptr; // null by default
    // _data should be a unique_ptr and declared like this : 
    // unique_ptr<Data> _data;

    // unique_ptr works with array too.


    // move constructor
    Bytearray (Bytearray&& other) {
        // we have the other's data, the other becomes null.
        swap(_data, other._data);
    }

    // move assignation
    Bytearray& operator=(Bytearray&& other) {
        // same thing here, we swap the data.
        swap(_data, other._data);
        // as we swap, we get the new data. 
        // Since other is temporary, our old data is deleted by other destructor.
        // No leak here.
    }

        // you could mark copy constructor and copy assignation as deleted here.
};

你走了!没有更多的副本,也没有更多的指针和参考。

答案 2 :(得分:-1)

以下是一种典型的做法。

void Bytearray::copy(int start, int end, Bytearray* b){
  for(int i = start; i < end; i++){
    b->_data[i-start] = _data[i];
  }
}

...

Bytearray aa(4);
bb.copy(1, 5, &aa);