編輯:我再次問同樣的問題在這裏(固定這個問題提出的問題後):Why does this C++0x program generates unexpected output?的C++ 0x移動構造函數疑難雜症
的基本思路是,指向可移動的東西可能淨你如果你不小心,會有一些奇怪的結果。
C++移動構造函數和移動賦值運算符看起來非常積極。它們可以用於複製構造函數沒有意義的情況,因爲它們不需要指向重複的資源。
但有些情況下,他們會咬你,如果你不小心。這是特別相關的,因爲我看到了允許編譯器生成移動構造函數的默認實現的提議。如果有人能給我一個,我會提供一個鏈接。
所以,這裏有一些代碼有一些可能不完全明顯的缺陷。我測試了代碼以確保它在g ++中使用-std=gnuc++0x
標誌進行編譯。這些缺陷是什麼,你將如何解決它們?
#if (__cplusplus <= 199711L) && !defined(__GXX_EXPERIMENTAL_CXX0X__)
#error This requires c++0x
#endif
#include <unordered_set>
#include <vector>
#include <utility>
#include <algorithm>
class ObserverInterface {
public:
virtual ~ObserverInterface() {}
virtual void observedChanged() = 0;
virtual void observedGoingAway() = 0;
};
class Observed {
private:
typedef ::std::unordered_set<ObserverInterface *> obcontainer_t;
public:
Observed() {}
Observed(const Observed &) = delete;
const Observed &operator =(const Observed &b) = delete;
// g++ does not currently support defaulting the move constructor.
Observed(Observed &&b) : observers_(::std::move(b.observers_)) { }
// g++ does not currently support defaulting move assignment.
const Observed &operator =(Observed &&b) {
observers_ = ::std::move(b.observers_);
return *this;
}
virtual ~Observed() {
for (auto i(observers_.begin()); i != observers_.end(); ++i) {
(*i)->observedGoingAway();
}
}
void unObserve(ObserverInterface *v) {
auto loc(observers_.find(v));
if (loc != observers_.end()) {
observers_.erase(loc);
}
}
void changed() {
if (!observers_.empty()) {
// Copy observers_ to bector so unObserve works
::std::vector<ObserverInterface *> tmp;
tmp.reserve(observers_.size());
tmp.assign(observers_.begin(), observers_.end());
for (auto i(tmp.begin()); i != tmp.end(); ++i) {
(*i)->observedChanged();
}
}
}
private:
obcontainer_t observers_;
};
class Observer : public ObserverInterface {
public:
Observer() {}
Observer(const Observer &) = delete;
const Observer &operator =(const Observer &b) = delete;
// g++ does not currently support defaulting the move constructor.
Observer(Observer &&b) : observed_(b.observed_) {
b.observed_ = 0;
return *this;
}
// g++ does not currently support defaulting move assignment.
const Observer &operator =(Observer &&b) {
observed_ = b.observed_;
b.observed_ = 0;
return *this;
}
virtual ~Observer() {
if (observed_) {
observed_->unObserve(this);
observed_ = 0;
}
}
virtual void observedChanged() {
doStuffWith(observed_);
}
virtual void observedGoingAway() {
observed_ = 0;
}
private:
Observed *observed_;
// Defined elsewhere
void doStuffWith(Observed *);
};
這是一個測驗嗎?你知道缺陷是什麼嗎? – 2010-01-24 22:38:42
沒有「正確的」答案,因爲這需要討論。更好的社區維基它,如果你想這甚至有機會沒有結束...... – Earlz 2010-01-24 22:40:15
@Greg Hewgill,我知道什麼是缺陷。我注意到,有幾個人提問他們知道答案,因爲他們認爲問題的答案對網站有用和有指導意義。這是一個這樣的問題。 – Omnifarious 2010-01-24 22:41:43