Если право собственности на управляемый объект не передается (а потому, что это 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);
Update:
отмечая обновление на вопрос - хранение (не владеющие) ссылок на этот объект.
Один из способов сделать это - действительно хранить указатель. Тем не менее, указатели страдают от возможности логической ошибки в том, что они могут юридически быть нулевыми. Другая проблема с указателями заключается в том, что они не играют хорошо с 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&
, вы можете используйте объект reference_wrapped
в любом выражении, которое ожидало бы T
.
, например:
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
У вас не может быть 'unique_ptr' и' shared_ptr', которые управляют одним и тем же объектом. –
Передача ссылки на упомянутый объект - хорошая идея. –