C++ Vector of pointers, add referenced variable - c++

I have a vector of pointers to an object:
vector<Foo*> bar;
In a method, I am given an Foo object and need to add it to the vector. This is my current attempt:
void push(const Foo &a){
bar.insert(bar.begin(), a);
}
I know this doesnt work because a was passed as a reference, but I can't seem to get the pointer for a to add to bar.
How can I add a to the vector bar?

You can't put an object in a container of pointers.
If you want to put an object in, then you'll need a container of objects:
vector<Foo> bar;
In that case, all the objects must be of the same type; if Foo is actually a base class, and you want to store a variety of different derived types, then you'll need to store pointers.
If you want a container of pointers, then you'll need to put a pointer in it:
bar.insert(bar.begin(), &a);
In that case, you need to take care with the object's lifetime, and make sure you don't use the pointer after the object is destroyed. Smart pointers might be helpful.

Add the address of a. Pointers store addresses, which is how they point to something.
bar.insert(bar.begin(), &a);
I'm presuming you have a good reason for using pointers, but make sure the a being passed in isn't temporary and that the object you pass in outlives the vector so that you don't end up with a dangling pointer.

Correct me if I am wrong, but a is not a pointer in that code, even though it is passed by reference. You should be able to use & on it to gets it's address, correct?

Just take the address of a. The reference really is just that, a reference, so taking the address of it actually yields the address of what it refers to.
void push(const Foo& a)
{
bar.insert(bar.begin(), &(a));
}

Related

Pass in unique pointer for inherited class to constructor with unique pointer for base class?

Is it possible to do the following: I have an inherited class B from base class A. I want to create a constructor for a method that takes in a unique pointer to class A but still accept unique pointers to class B, similar to pointer polymorphism.
void Validate(unique_ptr<A> obj) {obj->execute();}
...
unique_ptr<B> obj2;
Validate(obj2);
This doesn't seem to work as I've written it (I get a No matching constructor for initialization error), but I wonder if this is still possible?
Your issue doesn't really have anything to do with polymorphism, but rather how unique_ptr<> works in general.
void Validate(unique_ptr<A> obj) means that the function will take ownership of the passed object. So, assuming that this is what the function is meant to do, you need to handoff said ownership as you call it.
In the code you posted, you would do this by moving the existing std::unique_ptr<>. This will ultimately (as in not by the call to std::move() itself, but the handoff as a whole) null-out the original pointer. That's the whole point of unique_ptr<> after all: There can only be one of them pointing at a given object.
void Validate(unique_ptr<A> obj) {obj->execute();}
...
unique_ptr<B> obj2;
Validate(std::move(obj2));
// obj2 is now null.
By extension, if Validate() is not meant to take ownership of obj, then it should not accept a unique_ptr<> in the first place. Instead, it should accept either a reference or a raw pointer depending on whether nullptr is an expected valid value:
Ideally:
void Validate(A& obj) {
obj.execute();
}
...
unique_ptr<B> obj2;
Validate(*obj2);
Alternatively:
void Validate(A* obj) {
if(obj) {
obj->execute();
}
}
...
unique_ptr<B> obj2;
Validate(obj2.get());
You cannot copy a unique pointer.
If you wish to transfer the ownership to the Validate function, then you must move from the unique pointer:
Validate(std::move(obj2));
A unique pointer parmeter accepted by Validate implies that it takes ownership, but that design sounds odd given the name of the function - but that may be due to missing context.
If ~A isn't virtual, then you may not use std::unique_ptr<A> because it would try to destroy the object through a pointer to the base which would result in undefined behaviour. You could use a custom deleter in such case.
If you don't wish to transfer ownership but instead the function should just access the object, then don't use a unique pointer parameter in the first place. Use a reference instead:
void Validate(A& obj) {
obj.execute();
}
It doesn't matter whether the caller has a smart pointer or even whether the object is allocated dynamically.
You can use a bare pointer if you need to represent null, but if you don't need it (as is implied by your attempted implementation), then it's better to use reference since being able to avoid checking for null makes it easier to write a correct program.

C++ callbacks from objects managed by std::unique_ptr

I have a C++ project where I store objects in cells in a grid container. Every cell may contain one or zero objects stored in a std::unique_ptr. Naturally all methods having these objects as arguments should take a const std::unique_ptr reference to maintain the "uniqueness".
Secondly, when something happens to the objects they emit a signal with themselves as one of the arguments; these signals are caught by the grid container in a single handler (therefore we need the object reference). The handler may take some action on the object or emit its own signal, passing the object reference further.
The problem is that the objects themselves obviously cannot return a std::unique_ptr reference to themselves, while all other methods operating on them expects one. Is there a way to solve this, or do I have to let go of unique pointers and use raw ones?
Here's a code example using the sigc++ library (please allow for minor errors since I haven't tested it):
class Inhabitant
{
public:
void sos()
{
signal_distress.emit (*this);
}
// Signals
sigc::signal<void, Inhabitant &> signal_distress;
};
class Cell
{
public:
std::unique_ptr<Inhabitant> set_inhabitant (std::unique_ptr<Inhabitant> inhabitant)
{
// Set new inhabitant, return previous one...
}
private:
std::unique_ptr<Inhabitant> m_inhabitant;
};
class Grid
{
public:
void add_inhabitant_at (std::unique_ptr<Inhabitant> inhabitant,
unsigned int x, unsigned int y)
{
// Connect the inhabitant to our rescue team
inhabitant->signal_distress.connect (sigc::mem_fun (*this,
&Grid::on_inhabitant_distress));
// Place in cell
m_cells[x][y].set_inhabitant (std::move (inhabitant));
}
private:
// Data
Cell m_cells[100][100];
// Helpers
void help_inhabitant (const std::unique_ptr<Inhabitant> &inhabitant)
{
// Do something helpful
}
// Signal handlers
void on_inhabitant_distress (Inhabitant &inhabitant)
{
// Now, how do I call help_inhabitant(), or any other function that expects
// a unique_ptr reference?
}
};
It is a best practice not to pass smart pointers such as unique_ptr to functions that do not need to take (or share) ownership of the resource managed by the unique_ptr. Put another way, I don't think you would ever want to pass a unique_ptr by const reference. Instead, all the functions that are taking these unique_ptr references really only need to take a const Inhabitant &. For example:
void help_inhabitant (const Inhabitant &inhabitant) {
// do stuff with the inhabitant directly
}
Naturally all methods having these objects as arguments should take a const std::unique_ptr reference to maintain the "uniqueness".
No, the object still has a single unique owner, no matter how many other pieces of code can access it via non-owning pointers or references. Your idea that passing around const unique_ptr<T>& maintains any kind of invariant or enforces a policy is an illusion.
Is there a way to solve this, or do I have to let go of unique pointers and use raw ones?
You don't have to give it up competely, just where it's inappropriate. Use unique_ptr for managing ownership and lifetime, use raw pointers for simply referring to an object that is managed by some other piece of code.
surely the whole point about unique_ptr is that you pass references to it, rather than a raw pointer?
No, definitely not.
The unique_ptr manages the ownership of the object, but not doesn't have to be used for access to the object.
If you want to refer to the object without owning it then passing references or pointers to the object is fine (as long as the code receiving those pointers or references doesn't think it is taking ownership and try to delete the object). The code that just wants to use Inhabitant doesn't need to care that it is owned by a unique_ptr, it just wants to use the object. How its lifetime is managed is someone else's concern, and the code that doesn't own the object should not be made dependent on the ownership policy. Avoiding that dependency would allow you to change the owner to use shared_ptr or some other mechanism, and the signal handlers would be unaffected because they do not have to change how they access the object.
Pass a unique_ptr by value (or rvalue reference) to transfer ownership. Do not pass a unique_ptr by const-reference, because it's completely useless, the caller can't do anything with it that can't be done with a raw pointer.
Using a reference to a unique_ptr actually introduces a new class of bug that wouldn't exist otherwise:
void register_callback(func_type f, const unique_ptr<T>& obj);
unique_ptr<T> p(new T);
register_callback(func, p); // stores reference to p
unique_ptr<T> p2 = std::move(p);
Now the signal handler still refers to p which is going to be empty when the callback happens. The identity of the unique_ptr is completely irrelevant, all that matters is that exactly one unique_ptr object owns the pointer, it doesn't matter which one owns it. But you have made the callback depend on the exact instance of unique_ptr by binding a reference to it, so you cannot move that (so you can never move a Cell, which means you can't store it in a container such as vector that might reallocate and move its elements)
If you do it this way instead the callback refers to the object, and it doesn't matter precisely where it's stored:
void register_callback(func_type f, T* obj);
unique_ptr<T> p(new T);
register_callback(func, p.get()); // stores p.get()
unique_ptr<T> p2 = std::move(p);
The callback's copy of the p.get() pointer remains valid even though ownership of it transfers from one object to another.
OK, solved the problem when I realized there is no reason why the cell inhabitants should send a reference to themselves with the signal. Instead the listener (the grid) can bind a reference to the inhabitant (the unique_ptr to it, that is) when registering with the signal:
inhabitant->signal_distress().connect (std::bind (&Grid::on_inhabitant_distress,
this,
std::cref (inhabitant));
This way the signal handler can take a unique_ptr:
void on_inhabitant_distress (const std::unique_ptr<Inhabitant> &inhabitant)
{
// Now everything is fine!
help_inhabitant (inhabitant);
}
and the "uniqueness" chain stays intact.

unique_ptr and polymorphism

I have some code that currently uses raw pointers, and I want to change to smart pointers. This helps cleanup the code in various ways. Anyway, I have factory methods that return objects and its the caller's responsibility to manager them. Ownership isn't shared and so I figure unique_ptr would be suitable. The objects I return generally all derive from a single base class, Object.
For example,
class Object { ... };
class Number : public Object { ... };
class String : public Object { ... };
std::unique_ptr<Number> State::NewNumber(double value)
{
return std::unique_ptr<Number>(new Number(this, value));
}
std::unique_ptr<String> State::NewString(const char* value)
{
return std::unique_ptr<String>(new String(this, value));
}
The objects returned quite often need to be passed to another function, which operates on objects of type Object (the base class). Without any smart pointers the code is like this.
void Push(const Object* object) { ... } // push simply pushes the value contained by object onto a stack, which makes a copy of the value
Number* number = NewNumber(5);
Push(number);
When converting this code to use unique_ptrs I've run into issues with polymorphism. Initially I decided to simply change the definition of Push to use unique_ptrs too, but this generates compile errors when trying to use derived types. I could allocate objects as the base type, like
std::unique_ptr<Object> number = NewNumber(5);
and pass those to Push - which of course works. However I often need to call methods on the derived type. In the end I decided to make Push operate on a pointer to the object stored by the unique_ptr.
void Push(const Object* object) { ... }
std::unique_ptr<Object> number = NewNumber(5);
Push(number.get());
Now, to the reason for posting. I'm wanting to know if this is the normal way to solve the problem I had? Is it better to have Push operate on the unique_ptr vs the object itself? If so how does one solve the polymorphism issues? I would assume that simply casting the ptrs wouldn't work. Is it common to need to get the underlying pointer from a smart pointer?
Thanks, sorry if the question isn't clear (just let me know).
edit: I think my Push function was a bit ambiguous. It makes a copy of the underlying value and doesn't actually modify, nor store, the input object.
Initially I decided to simply change the definition of Push to use
unique_ptrs too, but this generates compile errors when trying to use
derived types.
You likely did not correctly deal with uniqueness.
void push(std::unique_ptr<int>);
int main() {
std::unique_ptr<int> i;
push(i); // Illegal: tries to copy i.
}
If this compiled, it would trivially break the invariant of unique_ptr, that only one unique_ptr owns an object, because both i and the local argument in push would own that int, so it is illegal. unique_ptr is move only, it's not copyable. It has nothing to do with derived to base conversion, which unique_ptr handles completely correctly.
If push owns the object, then use std::move to move it there. If it doesn't, then use a raw pointer or reference, because that's what you use for a non-owning alias.
Well, if your functions operate on the (pointed to) object itself and don't need its address, neither take any ownership, and, as I guess, always need a valid object (fail when passed a nullptr), why do they take pointers at all?
Do it properly and make them take references:
void Push(const Object& object) { ... }
Then the calling code looks exactly the same for raw and smart pointers:
auto number = NewNumber(5);
Push(*number);
EDIT: But of course no matter if using references or pointers, don't make Push take a std::unique_ptr if it doesn't take ownership of the passed object (which would make it steal the ownership from the passed pointer). Or in general don't use owning pointers when the pointed to object is not to be owned, std::shared_ptr isn't anything different in this regard and is as worse a choice as a std::unique_ptr for Push's parameter if there is no ownership to be taken by Push.
If Push does not take owenrship, it should probably take reference instead of pointer. And most probably a const one. So you'll have
Push(*number);
Now that's obviously only valid if Push isn't going to keep the pointer anywhere past it's return. If it does I suspect you should try to rethink the ownership first.
Here's a polymorphism example using unique pointer:
vector<unique_ptr<ICreature>> creatures;
creatures.emplace_back(new Human);
creatures.emplace_back(new Fish);
unique_ptr<vector<string>> pLog(new vector<string>());
for each (auto& creature in creatures)
{
auto state = creature->Move(*pLog);
}

What does `*&` in a function declaration mean?

I wrote a function along the lines of this:
void myFunc(myStruct *&out) {
out = new myStruct;
out->field1 = 1;
out->field2 = 2;
}
Now in a calling function, I might write something like this:
myStruct *data;
myFunc(data);
which will fill all the fields in data. If I omit the '&' in the declaration, this will not work. (Or rather, it will work only locally in the function but won't change anything in the caller)
Could someone explain to me what this '*&' actually does? It looks weird and I just can't make much sense of it.
The & symbol in a C++ variable declaration means it's a reference.
It happens to be a reference to a pointer, which explains the semantics you're seeing; the called function can change the pointer in the calling context, since it has a reference to it.
So, to reiterate, the "operative symbol" here is not *&, that combination in itself doesn't mean a whole lot. The * is part of the type myStruct *, i.e. "pointer to myStruct", and the & makes it a reference, so you'd read it as "out is a reference to a pointer to myStruct".
The original programmer could have helped, in my opinion, by writing it as:
void myFunc(myStruct * &out)
or even (not my personal style, but of course still valid):
void myFunc(myStruct* &out)
Of course, there are many other opinions about style. :)
In C and C++, & means call by reference; you allow the function to change the variable.
In this case your variable is a pointer to myStruct type. In this case the function allocates a new memory block and assigns this to your pointer 'data'.
In the past (say K&R) this had to be done by passing a pointer, in this case a pointer-to-pointer or **. The reference operator allows for more readable code, and stronger type checking.
It may be worthwhile to explain why it's not &*, but the other way around. The reason is, the declarations are built recursively, and so a reference to a pointer builds up like
& out // reference to ...
* (& out) // reference to pointer
The parentheses are dropped since they are redundant, but they may help you see the pattern. (To see why they are redundant, imagine how the thing looks in expressions, and you will notice that first the address is taken, and then dereferenced - that's the order we want and that the parentheses won't change). If you change the order, you would get
* out // pointer to ...
& (* out) // pointer to reference
Pointer to reference isn't legal. That's why the order is *&, which means "reference to pointer".
This looks like you are re-implementing a constructor!
Why not just create the appropriate constructor?
Note in C++ a struct is just like a class (it can have a constructor).
struct myStruct
{
myStruct()
:field1(1)
,field2(2)
{}
};
myStruct* data1 = new myStruct;
// or Preferably use a smart pointer
std::auto_ptr<myStruct> data2(new myStruct);
// or a normal object
myStruct data3;
In C++ it's a reference to a pointer, sort of equivalent to a pointer to pointer in C, so the argument of the function is assignable.
Like others have said, the & means you're taking a reference to the actual variable into the function as opposed to a copy of it. This means any modifications made to the variable in the function affect the original variable. This can get especially confusing when you're passing a pointer, which is already a reference to something else. In the case that your function signature looked like this
void myFunc(myStruct *out);
What would happen is that your function would be passed a copy of the pointer to work with. That means the pointer would point at the same thing, but would be a different variable. Here, any modifications made to *out (ie what out points at) would be permanent, but changes made to out (the pointer itself) would only apply inside of myFunc. With the signature like this
void myFunc(myStruct *&out);
You're declaring that the function will take a reference to the original pointer. Now any changes made to the pointer variable out will affect the original pointer that was passed in.
That being said, the line
out = new myStruct;
is modifying the pointer variable out and not *out. Whatever out used to point at is still alive and well, but now a new instance of myStruct has been created on the heap, and out has been modified to point at it.
As with most data types in C++, you can read it right-to-left and it'll make sense.
myStruct *&out
out is a reference (&) to a pointer (*) to a myStruct object. It must be a reference because you want to change what out points at (in this case, a new myStruct).
MyClass *&MyObject
Here MyObject is reference to a pointer of MyClass. So calling myFunction(MyClass *&MyObject) is call by reference, we can change MyObject which is reference to a pointer. But If we do myFunction( MyClass *MyObject) we can't change MyObject because it is call by value, It will just copy address into a temporary variable so we can change value where MyObject is Pointing but not of MyObject.
so in this case writer is first assigning a new value to out thats why call by reference is necessary.

const_cast for vector with object

I understand that const_cast to remove constness of objects is bad,
I have the following use case,
//note I cannot remove constness in the foo function
foo(const std::vector<Object> & objectVec) {
...
int size = (int) objectVec.size();
std::vector<Object> tempObjectVec;
//Indexing here is to just show a part of the vector being
//modified
for (int i=0; i < (int) size-5; ++i) {
Object &a = const_cast<Object&> objectVec[i];
tempObjectVec.push_back(a);
}
foo1(tempObjectVec);
}
If i change tempObjectVec objects in foo1, will the original objects in ObjectVec change, I say yes since I am passing references, further is this efficient. Can you suggest alternatives.
Well, that depends on Object. But the Objects are being copied, when you pass them to push_back. You can check this by adding some debug code to the copy constructor. So if Object is well-behaved and keeps distinct copies separate, then foo1 can change the vector it gets all it likes.
A more efficient way to do this would be to have foo1 accept a start and end iterators:
void foo1(std::vector<Object>::const_iterator start,
std::vector<Object>::const_iterator end);
...
foo1(objectVec.begin(), objectVec.end() - 5);
If you don't use const_cast, then the type system will ensure that foo1 does not change any elements, as these are const_iterators.
Your tempObjectVec can't be a vector of references, so I presume it should be declared as something like:
std::vector<Object> tempObjectVec;
When you execute the tempObjectVec.push_back(a), a copy of the object will be made to push it into the tempObjectVec vector. Since this is making a copy, you shouldn't even need to use the const_cast to remove the constness, I'm not clear on why you needed to do that.
I believe this is the statement your looking for:
const_cast<std::vector<Object>&> (objectVec) this will return a reference to a non-const std::vector which should be palatable to foo1 (I'm assuming).
Modifying your original example:
foo(const std::vector<Object> & objectVec) {
...
foo1(const_cast<std::vector<Object> &>(objectVec));
}
However I do recommend looking at the actual requirements of foo1 that require it to use a non-const vector as you seem to be indicating that all your interested in is modifying the Object instances themselves.
As other ones already say, your vector's push_back takes the reference, but then it copies the object it references. So, at the end you end up with a copy of objectVec[i] within your tempObjectVec.
A vector can't store references, because they can't be assigned (assignments to it affect not the reference itself, but the object referenced instead), which is a requirement for objects to be held in a vector. References are also no objects. They don't have an own size. They therefor can't be pushed into an array or any vector. Usually you want to store pointers or smart pointers in such a container to reference some other object. Look into the boost pointer container library which looks like exactly what you want.