2016-02-19 45 views
1

最近,我經常通過爲operator=分配一個新值來重置對象。我的大多數課程都使用「複製和交換」慣用語定義了copy constructoroperator=。在大多數情況下,它工作正常,雖然效率不如以前,但大多並不重要。有一種情況下,這不起作用。它的時候需要在新對象的constructor之前調用destructor重置對象

注:最讓我使用這個類是不可複製

class Foo 
{ 
public: 
    Foo() : m_i(0) {} 
    Foo(int i) : m_i(i) {} 

    Foo(Foo&& rhs); 
    Foo& operator=(Foo rhs); 
    friend void swap(Foo& lhs, Foo& rhs); 

private: 
    Foo(Foo& rhs) {} // uncopyable object 

    int m_i; 
}; 

Foo::Foo(Foo&& rhs) 
: Foo() 
{ 
    swap(*this, rhs); 
} 

Foo& Foo::operator=(Foo rhs) 
{ 
    swap(*this, rhs); 
    return *this; 
} 

void swap(Foo& lhs, Foo& rhs) 
{ 
    using std::swap; 
    swap(lhs.m_i, rhs.m_i); 
} 

int main() 
{ 
    Foo f(123); 
    f = Foo(321); // at one time both Foo(123) and Foo(321) exist in memory 
} 

然後我教給可能改寫operator=先手動調用destructor然後做swap(在這種情況下rhs會採用const引用)。然而this answer on stackOverflow讓我覺得不然。

我真的很喜歡operator =重置我的對象,因爲代碼是乾淨的,和內置類型(如int)相同。它還使用constructordestructor的代碼,因此不需要編寫和維護額外的代碼。

所以我的問題是:有沒有一種方法來實現我的目標,用乾淨的代碼重置我的對象,並且沒有額外的代碼要寫入,並且在構建新對象之前破壞對象?

回答

1

根據定義,如果您將賦值爲給舊對象一個新值,則在賦值發生之前就已經創建了新值。

你的'舊物體'也沒有真正被破壞。

所以沒有沒有辦法。並且不應該:您不應該重新定義賦值運算符的「明顯」行爲。

但放置新會除了波浪和異國情調的建築語法幫助這裏,也許這段代碼接近「乾淨」 :)

Foo old(a, b, c); 
old.~Foo(); // explicit destruction 
new (&old) Foo(d, e, f); 
+0

我可以使用放置新語法來編寫reset()方法。感謝這個想法。 – rozina

1

如果在構造函數中有代碼需要由賦值運算符調用,則將該代碼放入私有成員函數中,並從析構函數和賦值運算符中調用該代碼。

你的對象不會被破壞(你不希望它是真的),但它會做與析構函數相同的事情。

+0

正如你看到的例子,有在體內無碼構造函數。然而,變量'm_i'被初始化。我想這個變量可以在構造函數的主體中設置,但這並不總是可行或可取的。什麼是重置對象的一般方法? – rozina