我正在编写一个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 =
。如何减少复制并提高效率。
答案 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);