如果被管理對象的所有權未被轉移(並且因爲它是unique_ptr
,所有權不能共享),那麼將被調用函數中的邏輯與所有權概念分開更爲正確。我們通過引用來呼叫。
這是說的一個令人費解的方式:
考慮:
std::unique_ptr<Thing> thing_ptr;
改變的事情:
// declaration
void doSomethingWith(Thing& thing);
// called like this
doSomethingWith(*thing_ptr);
用的東西,而無需修改它。
// declaration
void doSomethingWith(const Thing& thing);
// called like this
doSomethingWith(*thing_ptr);
唯一一次你想要提unique_ptr
在函數簽名是,如果你是轉移所有權:
// declaration
void takeMyThing(std::unique_ptr<Thing> p);
// call site
takeMyThing(std::move(thing_ptr));
你永遠需要做到這一點:
void useMyThing(const std::unique_ptr<Thing>& p);
這是一個壞主意的原因是,如果將useMyThing的邏輯與所有權的概念相混淆,從而縮小了重用的範圍。
考慮:
useMyThing(const Thing& thing);
Thing x;
std::unique_ptr<Thing> thing_ptr = makeAThing();
useMyThing(x);
useMyThing(*thing_ptr);
更新:
注意到更新的問題 - 存儲(無所屬)到該對象的引用。
這樣做的一種方法的確是存儲指針。然而,指針受到邏輯錯誤的可能性,因爲它們可以合法地爲空。指針的另一個問題是它們不能很好地與std:: algorithms
和容器搭配使用 - 需要自定義比較函數等。
有做這個std::-compliant
方式 - std::reference_wrapper<>
所以,與其這樣:
std::vector<Thing*> my_thing_ptrs;
做到這一點:
std::vector<std::reference_wrapper<Thing>> my_thing_refs;
由於std::reference_wrapper<T>
定義操作T&
,你可以在期望T
的任何表達式中使用reference_wrapped
對象。
例如:
std::unique_ptr<Thing> t1 = make_thing();
std::unique_ptr<Thing> t2 = make_thing();
std::unique_ptr<Thing> t3 = make_thing();
std::vector<std::reference_wrapper<const Thing>> thing_cache;
store_thing(*t1);
store_thing(*t2);
store_thing(*t3);
int total = 0;
for(const auto& t : thing_cache) {
total += value_of_thing(t);
}
其中:
void store_thing(const Thing& t) {
thing_cache.push_back(std::cref(t));
}
int value_of_thing(const Thing& t) {
return <some calculation on t>;
}
爲什麼不傳遞unique_ptr對象的引用? – Zaiborg 2015-02-23 10:57:21
你不能有'unique_ptr'和'shared_ptr'管理同一個對象。 – 2015-02-23 10:58:13
將引用傳遞給引用的對象,這是一個好主意。 – 2015-02-23 10:59:14