To prevent that particular case, you can choose to either take a pointer (since Weep(&std::vector<int>{1,2,3})
isn't allowed) or you could take a non-const reference which will also error on a temporary.
Woop(const std::vector<int> *nums);
Woop(std::vector<int> *nums);
Woop(std::vector<int>& nums);
These still don't guarantee the value remains valid, but stops the easiest mistake at least, doesn't create a copy, and doesn't need nums
be created in a special way (e.g. as std::shared_ptr
or std::weak_ptr
does).
std::scoped_lock
taking a reference to the mutex would be an example, and one where unique/shared/weak ptr is not really wanted. Often the std::mutex
will just be a basic member or local variable. You still have to be very careful, but in these cases it is generally easy to determine the life span.
std::weak_ptr
is another option for non-owning, but then you force the caller to use shared_ptr
(and thus also heap allocate), and sometimes that isn't wanted.
If a copy is OK, that just avoids the issue.
If Woop
should take ownership either pass as an r-value and move (and avoid pointer/reference issues entirely), or use unique_ptr
if you can't move the value itself or want the pointer to remain valid.
// the caller can't continue to use nums, they could however get `numbers` from Woop or such like
// or just let Woop only manipulate numbers directly.
Woop(std::vector<int> &&nums)
: numbers(std::move(nums)) {}
std::vector<int> numbers;
// while the caller looses the unique_ptr, they might still use a raw pointer, but be careful.
// Or again access numbers only via Woop as with the move construct above.
Woop(std::unique_ptr<std::vector<int>> &&nums)
: numbers(std::move(nums)) {}
std::unique_ptr<std::vector<int>> numbers;
Or if ownership is shared, you can use shared_ptr
for everything, and it will be deleted along with the final reference, but this can make keeping track of object life cycles get very confusing if over-used.