I am trying to give the nullpointer wrapped as a unique pointer as the default argument to a function. Using only pointers the header might look like this
double f(A* vec = nullptr);
Since I do however need to use a unique_ptr, I tried to change it to
double f(std::unique_ptr<A>& A vec = nullptr);
or
double f(std::unique_ptr<A>& A vec = std::unique_ptr<A>(nullptr));
Which results in the errors
could not convert ‘nullptr’ from ‘std::nullptr_t’ to ‘std::unique_ptr&’
and
cannot bind non-const lvalue reference of type ‘std::unique_ptr&’ to an rvalue of type ‘std::unique_ptr’
respecively. Is there a way to do this? I am relatively new to C++, so the answer might be obvious.
Not relevant to the question, but an explanation for my choice of unique_ptr: The parameter vec is used as the start value for an iteration in f and an improved value is returned with the pointer. The plan was that if no start value is given the pointer is set to the nullptr and a start value is calculated during the program. Since I however generate a new object, it would from all I can see be safer to use unique_ptr over a naked pointer.
I would say you have two optione here.
1) The function does not own the pointer it merely uses it. In this case pass a raw pointer or (better) a reference (if nullptr is not an option).
// correct way to express a call to a non-owning function.
double f(A* vec = nullptr);
Calling code will use the function like this:
std::unique_ptr<A> vec;
f(vec.get()); // pass the raw pointer to the function
2) The function needs to manage the life of the pointer or reseat the pointer (own it) in which case accept a std::unique_ptr by value.
// way to express transfer of ownership to a function
double f(std::unique_ptr<A> vec = std::unique_ptr<A>());
There is really no need to accept a reference if the function needs to take ownership of the pointer.
In discussions a third option has presented itself.
3) The function is expected to modify the pointer if you pass one in otherwise it will use its own internal pointer.
This is unusual but you could do this with a pair of overloaded functions like this:
// way to express a function that modifies a smart pointer
// (for example reseating it)
double f(std::unique_ptr<A>& vec);
// version where the uses doesn't want to supply the pointer
// and doesn't care about the modified value.
double f()
{
std::unique_ptr<A> vec; // a dummy
f(vec); // pass in the dummy
}
The second error is because you are binding a non-const reference to a rvalue (which it kind of says). If that is a must, you cannot use a default value, or use a const reference:
double f(const std::unique_ptr<A>& A vec = std::unique_ptr<A>(nullptr));
double f(std::unique_ptr<A>& vec = nullptr);
doesn't work since the compiler has to create a temporary std::unique_ptr from nullptr. Had you used
double f(std::unique_ptr<A> const& vec = nullptr);
the compiler would have accepted it.
One work around is to overload.
double f(std::unique_ptr<A>& vec)
{
return 0;
}
double f()
{
std::unique_ptr<A> vec = nullptr;
return f(vec);
}
Related
I've tried to read some posts regarding ownership of objects, and how some exceptions apply when copy-constructing a unique_ptr which essentially is forbidden. Of course I pass AND return it by reference, so no copying has to be involved.
std::unique_ptr<T>& ptr_func(std::unique_ptr<T>& p) {
return p;
}
Passing an instance of a pointer to this function, is no problem. It basically goes into the function and comes out unchanged, regardless what it points to.
Now comes my question: Imagine my pointer of interest is pointing to an object containing several attributes, and I can only retrieve this pointer in form of a function's return value, E.g.
std::unique_ptr<T>& ptr_func() //say this function returns my pointer.
Now, let's say it takes quite some computation to retrieve this pointer (e.g. by iterating through a large vector), and I want to set/get many different attributes of the object it points to. Then it becomes very impractical not to be able to have a second (temporary) handle to the pointer or object it is pointing to, as I have to call the function that returns the pointer, for every single action. The compiler DOES somehow create a second reference in one known case: Let's say I pass the function returning my pointer as argument to another function, that changes attributes of the object being pointed to:
void set_attributes(std::unique_ptr ptr) {
ptr->change_something();
ptr->change_something_else();
}
Like so:
void set_attributes(function_returning_pointer())
In this case, the function_returning_pointer() is only called once, regardless how many times its return value is used in the body of set_attributes()
How does this work?
std::unique_ptr<T>& ptr_func() is strange signature: you might take ownership... or not.
You probably want clearer functions:
T& get_ref();
T* get_ptr();
std::unique_ptr<T> take();
From your usage, set_attributes should be:
void set_attributes(MyObject& ptr) {
ptr.change_something();
ptr.change_something_else();
}
with usages similar to
assert(function_returning_pointer() != nullptr);
set_attributes(*function_returning_pointer());
assert(get_ptr() != nullptr);
set_attributes(*get_ptr());
set_attributes(get_ref());
auto ptr = take();
assert(ptr != nullptr);
set_attributes(*ptr); // set_attributes(*take()) would be useless as object would be destroyed.
If really you want to keep passing unique_ptr without transfer ownership, your method would be:
void set_attributes(std::unique_ptr<MyObject>& ptr) { // prefer MyObject& or MyObject* instead
assert(ptr != nullptr);
ptr->change_something();
ptr->change_something_else();
}
Can I pass a unique_ptr's reference to a function? If not why should I avoid it?
Ex:
void func(unique_ptr<Clss>& ref);
main() {
unique_ptr<Clss> a = std::make_unique<Clss>();
fn(a);
}
Can I pass a unique_ptr's reference to a function?
Yes, a unique_ptr is class like any other.
You should do this when you want to mutate an existing unique_ptr from a function (e.g. calling .reset() on it).
If only you want to access the object inside unique_ptr<T>, take T& or const T& in your function interfaces, so that they can be used independently of unique_ptr.
According to Herb Sutter:
https://herbsutter.com/2013/06/05/gotw-91-solution-smart-pointer-parameters/
Passing unique_ptr by reference is for in/out unique_ptr parameters.
void f( unique_ptr<widget>& ); // (d)
This should only be used to accept an in/out unique_ptr, when the function is supposed to actually accept an existing unique_ptr and potentially modify it to refer to a different object. It is a bad way to just accept a widget, because it is restricted to a particular lifetime strategy in the caller.
Thanks #sgvd
See this code snippet, two ways of passing unique_ptr as function parameter. fun1 will take ownership of the object ( hence should be forwarded from the caller) but func2 commits thats the reference unique_ptr object will be passed as reference and will not be modified by the function.
void func1(unique_ptr<Clss>&& moved_obj) // this function takes ownership
{
//do something with the moved_obj
moved_obj.reset();
}
void func2(const unique_ptr<Clss>& ref_obj) // this function takes reference
{
unique_ptr<Clss> new_obj = std::make_unique<Clss>(*(ref_obj));
}
int main() {
unique_ptr<Clss> a = std::make_unique<Clss>();
func1(std::move(a));
unique_ptr<Clss> b = std::make_unique<Clss>();
func2(b);
return 0;
}
I see those valid meaningful signatures:
void take_ownership(std::unique_ptr<Clss>);
// or void take_ownership(std::unique_ptr<Clss>&&);
void use(/*const*/ Clss*);
// or void use(/*const*/ Clss&);
std::unique_ptr<Clss> create(/*args..*/);
void might_take_ownership(std::unique_ptr<Clss>&);
The later might make sense, but it is more difficult to reason with (as any I/O argument).
If you can, prefer one of the other.
Passing a std::unique_ptr to a function is perfectly fine as long as you respect the same rules you would when passing a regular reference to a function:
the underlying std::unique_ptr and the object it points to must live at least as long as the function will use the reference;
in case of multi-threading, barriers must be put in place.
i'm using the new smart-pointer from C++ 11. I'm now confused what's the best way to pass and input value to an function.
The standard rule for method/function signatures is
inputs: prefer const reference and pointer where you must (f.e. nullptr is a legal input)
outputs: should b e pointers.
But with smart-pointer things are more "complicated".
I understand that you should not pass the input as ...
unique_ptr where the ownership is not transfered
shared_ptr where the object should not be share the ownership.
... and use referece or pointer instead.
For me the problem with the standard rule is that the developer who is using the function must dereference the pointer from the smart-pointer and he should always check if the result is not nullptr, so there is an "always" manual checking code.
void foo(const MyClass& obj)
{
...
}
void main()
{
auto a = make_unique<MyClass>();
if(*a) // always check dereference
{
foo(*a);
}
}
Instead, passing the input as const pointer, the usability is easier, but nullptr would be an "legal" value.
void foo(const MyClass* obj)
{
...
}
void main()
{
auto a = make_unique<MyClass>();
foo(a.get()); //easier to use, but nullptr is a "legal" value
}
Can anybody share his opinion when you use pointer, when references and how do you deal with deref's in that case.
Thanks in advance
If you are trying to check if the pointer points to an allocated object or if it is instead null, use std::unique_ptr::operator bool which will return true if the pointer is valid and false if there is no object created yet:
http://en.cppreference.com/w/cpp/memory/unique_ptr/operator_bool
This is better, and simpler, than using get() for this purpose.
Generally, with unique_ptr you do not pass the smart pointer itself to any functions, but when you want to pass a true pointer, you pass the return of get(), which is a non-owning normal pointer that the non-owning function can use. The pointer is still managed by the owning smart pointer. Common C++ guidelines encourage use of a normal pointer only for non-owning functions or classes that receive this pointer from a smart pointer elsewhere.
Background
If I had a function foo as follows
void foo(std::vector<int>& values)
{
values = std::vector<int>(10, 1);
}
Then I could call it as
std::vector<int> values;
foo(values);
Notice that the initial vector is empty, then it is populated within the function foo.
I often come across interfaces that I cannot change (i.e. 3rd party), that have the same intention as above, but using raw arrays, for example
void foo(int*& values)
{
values = new int[10];
std::fill_n(values, 10, 1);
}
My problem with these is that now I am responsible for managing that memory, e.g.
int* values;
foo(values);
delete[] values;
Question
Is there any way I can use smart pointers to manage this memory for me? I would like to do something like
std::unique_ptr<int[]> values;
foo(values.get());
but get returns a pointer that is an r-value, so I cannot pass it by non-const reference.
Create empty unique_ptr.
Create pointer.
Pass pointer to function.
Reset unique_ptr to that pointer.
Like that:
std::unique_ptr<int[]> values;
int* values_ptr;
foo(values_ptr);
values.reset(values_ptr);
Or:
int* values_ptr;
foo(values_ptr);
std::unique_ptr<int[]> values(values_ptr);
Simple answer: you cannot.
But i believe there is a way to simplify you life. Since you always do the same thing, you simply have to write a function that does it for you and call that function when you need. Since i suppose you want to use the returned value written in memory before releasing it, i make my function return it.
template <typename T, typename Function>
std::unique_ptr<T[]> call(Function f) {
T * value;
f(value);
return { value };
}
// then to use it
auto value = call<int>(foo);
Would that suit you?
The function could be improved to detect the difference for pointers to one object or to an array if you need it, and it could probably also be improved to detect automatically the needed parameter type so that you do not have to type it.
I have some confusion about the shared_ptr copy constructor. Please consider the following 2 lines:
It is a "constant" reference to a shared_ptr object, that is passed to the copy constructor so that another shared_ptr object is initialized.
The copy constructor is supposed to also increment a member data - "reference counter" - which is also shared among all shared_ptr objects, due to the fact that it is a reference/pointer to some integer telling each shared_ptr object how many of them are still alive.
But, if the copy constructor attempts to increment the reference counting member data, does it not "hit" the const-ness of the shared_ptr passed by reference? Or, does the copy constructor internally use the const_cast operator to temporarily remove the const-ness of the argument?
The phenomenon you're experiencing is not special to the shared pointer. Here's a typical primeval example:
struct Foo
{
int * p;
Foo() : p(new int(1)) { }
};
void f(Foo const & x) // <-- const...?!?
{
*x.p = 12; // ...but this is fine!
}
It is true that x.p has type int * const inside f, but it is not an int const * const! In other words, you cannot change x.p, but you can change *x.p.
This is essentially what's going on in the shared pointer copy constructor (where *p takes the role of the reference counter).
Although the other answers are correct, it may not be immediately apparent how they apply. What we have is something like this:
template <class T>
struct shared_ptr_internal {
T *data;
size_t refs;
};
template <class T>
class shared_ptr {
shared_ptr_internal<T> *ptr;
public:
shared_ptr(shared_ptr const &p) {
ptr = p->ptr;
++(ptr->refs);
}
// ...
};
The important point here is that the shared_ptr just contains a pointer to the structure that contains the reference count. The fact that the shared_ptr itself is const doesn't affect the object it points at (what I've called shared_ptr_internal). As such, even when/if the shared_ptr itself is const, manipulating the reference count isn't a problem (and doesn't require a const_cast or mutable either).
I should probably add that in reality, you'd probably structure the code a bit differently than this -- in particular, you'd normally put more (all?) of the code to manipulate the reference count into the shared_ptr_internal (or whatever you decide to call it) itself, instead of messing with those in the parent shared_ptr class.
You'll also typically support weak_ptrs. To do this, you have a second reference count for the number of weak_ptrs that point to the same shared_ptr_internal object. You destroy the final pointee object when the shared_ptr reference count goes to 0, but only destroy the shared_ptr_internal object when both the shared_ptr and weak_ptr reference counts go to 0.
It uses an internal pointer which doesn't inherit the contests of the argument, like:
(*const_ref.member)++;
Is valid.
the pointer is constant, but not the value pointed to.
Wow, what an eye opener this has all been! Thanks to everyone that I have been able to pin down the source of confusion to the fact that I always assumed the following ("a" contains the address of "b") were all equivalent.
int const *a = &b; // option1
const int *a = &b; // option2
int * const a = &b; // option3
But I was wrong! Only the first two options are equivalent. The third is totally different.
With option1 or option2, "a" can point to anything it wants but cannot change the contents of what it points to.
With option3, once decided what "a" points to, it cannot point to anything else. But it is free to change the contents of what it is pointing to. So, it makes sense that shared_ptr uses option3.