在C++ 11中,move-constructor/operator支持資源/內存移動。當使用移動構造函數時,將自身重置爲nullptr是否是一種好習慣?
這是我的例子:
class A {
public:
A() : table_(nullptr), alloc_(0) {}
~A()
{
if (table_)
delete[] table_;
}
A(const A & other)
{
// table_ is not initialized
// if (table_)
// delete[] table_;
table_ = new int[other.alloc_];
memcpy(table_, other.table_, other.alloc_ * sizeof(int));
alloc_ = other.alloc_;
}
A& operator=(const A & other)
{
if (table_)
delete[] table_;
table_ = new int[other.alloc_];
memcpy(table_, other.table_, other.alloc_ * sizeof(int));
alloc_ = other.alloc_;
return *this;
}
A(A && other)
{
// table_ is not initialized in constructor
// if (table_)
// delete[] table_;
table_ = other.table_;
alloc_ = other.alloc_;
}
A& operator=(A && other)
{
if (table_)
delete[] table_;
table_ = other.table_;
alloc_ = other.alloc_;
}
private:
int *table_;
int alloc_;
};
這似乎不錯,但有時我想搬到一個局部變量,就像這樣:
class B {
private:
A a_;
public:
void hello()
{
A tmp;
// do something to tmp
a_ = std::move(tmp);
// tmp.~A() is called, so a_ is invalid now.
}
};
當函數結束時,tmp.~A()
將被調用,此時,a_
和tmp
指針有相同的table_
,當tmp delete[] table_
,a_'s table_
將無效。
我在徘徊什麼時候應該使用std::move
將tmp分配給a_,無需複製。
與答案的幫助下,我修改A的舉動,構造是這樣的:
class A {
private:
void reset()
{
table_ = nullptr;
alloc_ = 0;
}
public:
A(A && other)
{
table_ = other.table_;
alloc_ = other.alloc_;
other.reset();
}
A& operator=(A && other)
{
std::swap(table_, other.table_);
std::swap(alloc_, other.alloc_);
}
};
在這段代碼,當我移動的東西,我將交換新老參考,所以老tmp
將刪除[]原來的a_table_,這是沒用的。
這是一個很好的習慣。
是的,我更新了我的問題,我的解決方案與您的解決方案是一樣的,爲所有課程編寫這種'move'函數是一種好習慣嗎? – linrongbin
@zhaochenyou是的,它的有效 – marcinj
謝謝,哈哈,我很高興我找到了一個很好的解決方案。 – linrongbin