I'm fairly new to C++ and just learned about smart pointers. Now I'm wondering what the best practice is to make sure that they are efficiently used (let's say my optimization algorithm requires hundreds of millions of objects to be created, evaluated [in relatives
] and then then safely discarded - ideally in a concurrent way).
I would appreciate if you could tell me if this is alright or if there is something else I'm supposed to do differently/better.
Edit: This sa simplified example to focus on the correct creation of the objects. Obviously, simple properties could be represented differently. Here, I am trying to focus on learning how to correctly create objects that reference other objects and may be referenced by many other objects before they are destroyed. So my question is if the code below is a reasonably fast and, more important, safe way to create objects.
class Property {
public:
int id;
};
class Pet {
const int id_;
const std::shared_ptr<Property> myProperty_;
const std::shared_ptr<Property> myProperty2_;
std::map<double, std::shared_ptr<Pet>> relatives; // one of the places where the object will be referenced, I use "HashMap" in my Java prototype
Pet(const int id, const std::shared_ptr<Property> myProperty, const std::shared_ptr<Property> myProperty2) :
id_(id), myProperty_(myProperty), myProperty2_(myProperty2) { }
const std::shared_ptr<Pet> makePet(const int id, const std::shared_ptr<Property> myProperty, const std::shared_ptr<Property> myProperty2) {
return std::make_shared<Pet>(id, myProperty, myProperty2);
}
};
As I mentioned before, eventually I hope to be able to implement something so multiple threads can access relatives
, but don't think this is relevant for the object creation (is it?).
Thank you in advance!
The concept of std::shared_ptr
is so cool that I had to use it everywhere in my first new project after it appeared! It enables RAII (A C++ explicit garbage collection method) for all objects pointed to being destroyed when the object owning the std::shared_ptr
is destroyed.
Now std::shared_ptr
has a few drawbacks, some with the concept and some with the implementation.
std::unique_ptr
std::shared_ptr<Pet> pet;
pet->control block->Pet object
Which is an external reference count, as opposed to where the reference count is part of the object.
pet->Counter + Pet object
So if your goal is to delete a Pet when there are no more refences to it there are different methods to do it.
using PetId = int;
std::unordered_map<PetId, std::shared_ptr<Pet>> PetDict; // global pet owner, hash map/dictionary
void ErasePet(PetId id) {
auto pet = PetDict.find(id);
if (pet != PetDict.end()) // can be avoided if you know id is in PetDict ... no, you can't be sure.
PetDict.erase(pet); // this is not enough as the relatives still keep the pet alive and will cause a dead pet to still have relations while not being findable anymore.
}
So before erasing the pet you will have to make the relatives
forget the pet, there are at least three ways to do this
relatives
to use std::weak_ptr
relatives
as the relation could have be erased.relatives
to use the PetId
instead of the std::shared_ptr<Pet>
relatives
as the relation could have be erased.relatives
to erase the relation in each of those.
relatives
is not indexed by PetId
, all nodes of relatives
must be check for the right PetId
, rather horrible O(m) but then how often ar pets deleted?The first two options are a kind of lazy delete as they can remove the relation once it is found that it is no longer active, though it will still cost in alive checking for every usage.
Regarding the thread safety, there are several variants.
std::shared_ptr
that is also OK, as the counter is the only part of std::shared_ptr
that is atomic.std::shared_ptr
points to in the control block, you get a race conditionstd::shared_ptr
points to you get a race condition.In C++20 std::atomic(std::shared_ptr) can help with atomic updates of the control block, but you still needs to make access to the pointed to object thread safe yourself. The usual cost benefits for how many readers/writes must be evaluated.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.