std::make_unique<Party>(something)
по существу эквивалентно std::unique_ptr<Party>(new Party(something))
, поэтому да, он создает новые копии Party
объектов, потому что вы просили об этом.
В конечном итоге здесь unique_ptr
не кажется правильнымвыбор: если ваш std::vector
уже является единственным владельцем (и менеджером времени жизни) объектов, вам не нужно ничего делать, вы можете просто использовать простые указатели / ссылки. Однако имейте в виду, что их действительность привязана к правилам аннулирования ссылок std::vector
- в частности, если он решит перераспределить (что может произойти, например, если вы сделаете push_back
), все указатели / ссылки станут недействительными.
std::unordered_map<std::string, Party*> map_;
std::vector<Party> parties_;
parties_.emplace_back("AAA");
parties_.emplace_back("BBB");
parties_.emplace_back("CCC");
Party *ptr = &parties_.back();
// Notice: if you do parties_.emplace_back("DDD") here
// ptr may become invalid
ptr->value_ = "XXX";
for (auto& p : parties_) {
std::cout << p.value_ << std::endl; // print: AAA\nBBB\nXXX
}
Если вы хотите быть изолированным от последствий перераспределения, но можете согласиться с тем, что std::vector
является владельцем и, следовательно, определяет срок жизни ваших объектов, вы можете иметь std::vector<std::unique_ptr<Party>>
(иопять же, держите простые указатели / ссылки на них повсюду)
std::unordered_map<std::string, Party*> map_;
std::vector<std::unique_ptr<Party>> parties_;
parties_.emplace_back(std::make_unique<Party>("AAA"));
parties_.emplace_back(std::make_unique<Party>("BBB"));
parties_.emplace_back(std::make_unique<Party>("CCC"));
Party *ptr = parties_.back().get();
// Notice: if you do parties_.emplace_back(std::make_unique<Party>("DDD"));
// ptr will remain valid
ptr->value_ = "XXX";
for (auto& p : parties_) {
std::cout << p.value_ << std::endl; // print: AAA\nBBB\nXXX
}
Это гарантирует, что объекты выделяются независимо от вектора, но если они будут удалены из вектора, они будут удалены.
OTOH, если вы хотите разделить права владения между вектором и картой, вы можете захотеть std::shared_ptr
(что, однако, не бесплатно, оно должно управлять подсчетом ссылок & co.):
std::unordered_map<std::string, std::shared_ptr<Party>> map_;
std::vector<std::shared_ptr<Party>> parties_;
parties_.emplace_back(std::make_shared<Party>("AAA"));
parties_.emplace_back(std::make_shared<Party>("BBB"));
parties_.emplace_back(std::make_shared<Party>("CCC"));
std::shared_ptr<Party> ptr = parties_.back();
// Notice: if you do parties_.emplace_back(std::make_unique<Party>("DDD"));
// ptr will remain valid, but it will still be valid even after
// parties_.pop_back() (ptr will keep the pointed object alive)
ptr->value_ = "XXX";
for (auto& p : parties_) {
std::cout << p.value_ << std::endl; // print: AAA\nBBB\nXXX
}
Это гарантирует, что время жизни объектов не привязано к времени жизни вектора, так как любая копия оригинала std::shared_ptr
будет (1) указывать на тот же объект и (2) сохранить его в живых.