I'm trying to understand how to model ownership properly in C++, and I'm having trouble precisely understanding who owns what when.
For example I had a class like this, with a very complex init list and complex members who also have complex init lists.
class ComplexClass {
public:
OtherComplexClass1 foo1;
OtherComplexClass2 foo2;
//...
OtherComplexClassN fooN;
ComplexClass(
int arg1, int arg2, int arg3) :
foo1(OtherComplexClass1{arg1,arg2}),
foo2(OtherComplexClass2{arg3}),
//...
fooN(OtherComplexClassN{foo1,foo2,foo3,foo4})
{};
};
Using this I was able to allocate like so
auto my_class = ComplexClass(1,2,3);
and use the class fine. However now I want to make a dynamic number of these so I tried this
auto my_vec = std::vector<ComplexClass>{};
my_vec.emplace_back(ComplexClass{1,2,3});
But doing this I had a lot of memory errors. When I instead do
auto my_vec = std::vector<std::unique_ptr<ComplexClass>>{};
my_vec.emplace_back(std::make_unique<ComplexClass>(1,2,3));
everything seems to be working. My question is, why does the second way work and not the first?
Thank you
EDIT:
Added more precise description of error(s)
Added more precise example of object structure
(1) I actually have two scenarios. One is the one I described
auto my_vec = std::vector<ComplexClass>{};
my_vec.emplace_back(ComplexClass{1,2,3});
with the code in a free function (catch2 test).
The other is where I actually have the above, but inside the constructor of a holding class.
In the first case I get
==60617==ERROR: AddressSanitizer: heap-use-after-free
indicating a member function of one of the complex classes. In the second case I get ==60565==ERROR: AddressSanitizer: heap-use-after-free indicating a std::dequeue member of one of the complex classes.
(2) The ComplexClass and OtherComplexClassK tree goes a few levels deep, and many members somewhere in the tree are references to other members in the tree. Maybe that's causing the problem? I have made sure that all references are references to a member that is ultimately constructed in an init list.
The remarks so far have been very helpful.
Your class should be default-constructible, copy-assignable and copy-constructible. See this answer: https://stackoverflow.com/a/33110129/5132939 for more details. Also it's desired to make it move-constuctible and move-assignable. In some cases std::vector will use move semantics instead of copy.
Aggregate initialisation does not comply with user-declared constructors.
Related
I would like to know if there are any problems with the construction <type>*&& in C++. Let me give a concrete example.
Say we have a class that should be constructed from an array. We would usually do something like this:
class Things
{
public:
Things(const ThingType* arrayOfThings, int sizeOfArray)
: myArray(new ThingType[sizeOfArray])
{
for (int i = 0; i < sizeOfArray; i++)
myArray[i] = arrayOfThings[i];
}
private:
ThingType* myArray;
}
This is fine if we want to preserve arrayOfThings, because we are doing a deep copy of it. Moreover, by using const we are ensuring it won't be modified inside the constructor.
But suppose our program has a lot of statements like this one:
Things myThings(new ThingType[9001] {thing_0, ... , thing_9000}, 9001);
This might seem weird, but it may happen that the huge ThingType array is returned from a function as a rvalue.
In that case, we don't care about preserving the pointer passed as a parameter. In fact, we definitely don't want to do a deep copy of it, because it would be a huge waste of time preserving something we are about to destroy anyways.
One possible solution to this would to add another constructor that would handle the case of a non-const rvalue ThingType pointer, like a general move constructor handles the case of a non-const rvalue instance of the class:
public:
Things(ThingType*&& arrayOfThings, int sizeOfArray)
: myArray(arrayOfThings)
{
arrayOfThings = NULL;
}
This seems to be solving the problem for me, but I did not find much information about the <type>*&& construction seen above. Is it kosher, or will I be sent to the dungeons for mixing pointers and references?
After some time I believe I found satisfactory - although far from optimal - solutions. Since no one answered the question, I will share the best workarounds I found.
As Justin pointed out, using ThingType*&& can lead to trouble when we take the address of a variable of ThingType (but not of a ThingType pointer, as he implied in his answer) in the constructor call.
If t is a ThingType, the expression &t is an r-value of type ThingType*, so Thing myThing(&t, ...) will call the move constructor, with the result of making myThing.myArray point to t. This is not what we would want in most cases.
One solution is to use vectors instead of arrays, as illustrated below:
// Copy
explicit Things(const std::vector<ThingType>& vectorOfThings)
: myVector(vectorOfThings)
{ }
// Move
explicit Things(std::vector<ThingType>&& vectorOfThings)
: myVector(std::move(vectorOfThings))
{ }
The move constructor would then be used in situations like this:
Things myThings(vector<ThingType>{thing_0, ... , thing_9000});
Although this solves the problem, it is not feasible if we are dependent on an API which returns raw pointers, or if we want don't want to give up arrays. In this case, we can use smart pointers to solve the problem.
Suppose, we have a function ThingType* generateArray() which we want to use to initialize our object of type Things. The first thing we should do is to wrap this function with another function that returns a smart pointer instead.
unique_ptr<ThingType[]> generateSmartPointer()
{
return unique_ptr<ThingType[]>(generateArray());
}
Here I used a unique_pointer, but this could change depending on the implementation.
Now we add a new constructor to Things, with a instance of unique_ptr as an argument. This will act as the move constructor for arrays of ThingType:
Things(unique_ptr<ThingType[]> thingsPointer, int sizeOfArray)
: myArray(thingsInput.release()), size(sizeOfArray)
{ }
unique_ptr<T>.release() is used to get the array, and at the same time make the unique pointer release ownership of it, preventing the array from being deleted once the unique pointer is destroyed.
And that's it. These are the two best solutions I found to this problem, and while they are far from perfect, they have worked so far considering the objectives for each implementation.
Okay, so I have a large vector say
vector<vector<vector<int>>>
of 10000 by 10000 by 10000.
I have a class which has such a vector as a private member variable:
class foo {
private:
vector<vector<vector<int>>> myvector
};
I have a constructor for my class that uses pass by reference and initializer list:
foo(vector<vector<vector<int>>> &myvector_in) : myvector(myvector_in);
I want to know what's exactly happening in terms of memory usage. Is the private myvector the same as the one that was originally declared, or is it a copy.
Basically, I want to know if there are ever two version of myvector in memory.
Thank You!
Here is a fishing tip.
Fairly easy to answer yourself. Set [0][0][0] of myvector_in to a known value. Invoke the constructor and inside it also set [0][0][0] but of myvector to a different value. Once the constructor has returned, print the content of myvector_in. If it's the same as the one you original set you must conclude that the two vectors are different entities, thus one was copied into a different one. If they are the same than you can conclude they are in fact the same instances.
You could also print addresses to get a better sense of what's what.
I must point out, the memory requirement mention in your original question are in the realm of super computer, you got one?
You have a member of type vector<vector<vector<int>>> and initialize it with another vector<vector<vector<int>>>. How would it be possible not to have said data twice in memory? Thats more a matter of logic than a matter of c++.
Alternatives
You could store a pointer vector<vector<vector<int>>>* or a reference vector<vector<vector<int>>>& to the vector in an appropriate class member. Or use one of the smart pointers to do so. In any of these cases some serious thinking about memory management is a good idea.
Or you use a move constructor, which is moving the passed in vector in your member vector.
using vec = std::vector<std::vector<std::vector<int>>>;
class foo {
public:
foo() = delete;
foo(const vec&) = delete;
foo(vec&& myvector_in) : myvector(std::move(myvector_in)) {};
private:
vec myvector;
};
Of course that will render that argument passed to the constructor useless but that a trivial consequence of the not-copying you want.
You can pass your vector to that constructor if you first cast it to an rvalue using std::move:
foo my_foo(std::move(test));
The easy way of addressing this issue in C++11 (and newer) is to accept the constructor argument by value:
struct foo {
using vec=std::vector<std::vector<std::vector<int>>>; // from DrSvanHay
foo(vec v) : myvector(std::move(v)) {}
private:
vec myvector;
};
Surprisingly, this actually minimizes copies:
If the client has a vector cv;, cv gets copied into the parameter v, but that copy was necessary to have cv and foo::myvector upon completion.
If the client passes std::move(cv), cv gets moved into v and there is no copy.
If the client passes make_vector(...), the parameter v is move-initialized from the return value (or, in C++17, is the return value).
(In all these cases, v is then moved into foo::myvector, of course.)
I'm looking to do simulations with very complicated initial conditions from the user. I'm writing class A whose member variables need to be initialized by the user before running A.Solve() to get the results stored in a file. The initialization is rather complicated and requires several temporary data structures that will no longer be needed after the initialization. So, I wrote another class called class Initializer which stores a reference to an object of class A. My code will look like this:
class A {
friend class Initializer;
private:
// member variables storing the state of the system
public:
void Solve();
...
};
class Initializer {
private:
A& a
// Other data structures used in the initialization
...
public:
// functions called by the user to set up for the initialization
...
Initialize(); // after this is called, a will be ready to solve
};
int main(...) {
A a;
Initializer init(a);
// call functions on init to initialize the system
...
init.Initialize();
a.Solve();
return 0;
}
But it seems like data structures in init will live on the stack for the entire program. To prevent that, is it ok to do this:
A a;
Initializer *init = new Initializer(a);
....
init.Initialize();
delete init;
a.Solve();
Or does this look unnecessary and should I just have everything contained in class A?
To answer your original line of thought, the usual solution is to restrict the scope of the init variable:
A a;
{
Initializer init(a);
//...
} // init is destroyed as soon as the scope exits
a.Solve();
Your new/delete variant is quite brittle and will leak memory if anything throws between new and delete. To fix that, use smart pointers:
A a;
std::unique_ptr<Initializer> init(new Initializer(a));
//...
init.reset();
a.Solve();
However as others have said, this whole design is kinda weird and probably overkill. If the initialization is really so complicated that you can't get away with constructors then you may want to do it the other way around: instead of Initializer taking an argument A and operating on it, you should pass a fully ready-to-use Initializer to A's constructor, which will in turn either copy the whole Initializer to keep a copy of the data, or just copy the relevant bits. Initializer should then probably be renamed to Config or something like that. Notice how a Config/Initializer object can now be reused to initialize several A objects, and even be modified between two A initializations.
Unfortunately this is hard to give you definitive advice with so little information.
Note: if you use C++11 you may be interested in std::initializer_list which enables the new brace-initialization syntax. Depending on the complexity of your data it may involve more work than your current solution but you'll end up with a very nice and intuitive syntax.
Here, using another class for initialization purpose seem to be overkill.
Just initialize in class A constructor.
Once the constructor execution completes, the temporary data structures will be freed automatically.
I'm not a very experienced c++ coder and this has me stumped. I am passing a object (created elsewhere) to a function, I want to be able to store that object in some array and then run through the array to call a function on that object. Here is some pseudo code:
void AddObject(T& object) {
object.action(); // this works
T* objectList = NULL;
// T gets allocated (not shown here) ...
T[0] = object;
T[0].action(); // this doesn't work
}
I know the object is passing correctly, because the first call to object.action() does what it should. But when I store object in the array, then try to invoke action() it causes a big crash.
Likely my problem is that I simply tinkered with the .'s and *'s until it compiled, T[0].action() compliles but crashes at runtime.
The simplest answer to your question is that you must declare your container correctly and you must define an appropriate assigment operator for your class. Working as closely as possible from your example:
typedef class MyActionableClass T;
T* getGlobalPointer();
void AddInstance(T const& objInstance)
{
T* arrayFromElsewhere = getGlobalPointer();
//ok, now at this point we have a reference to an object instance
//and a pointer which we assume is at the base of an array of T **objects**
//whose first element we don't mind losing
//**copy** the instance we've received
arrayFromElsewhere[0] = objInstance;
//now invoke the action() method on our **copy**
arrayFromElsewhere[0].action();
}
Note the signature change to const reference which emphasizes that we are going to copy the original object and not change it in any way.
Also note carefully that arrayFromElsewhere[0].action() is NOT the same as objInstance.action() because you have made a copy — action() is being invoked in a different context, no matter how similar.
While it is obvious you have condensed, the condensation makes the reason for doing this much less obvious — specifying, for instance, that you want to maintain an array of callback objects would make a better case for “needing” this capability. It is also a poor choice to use “T” like you did because this tends to imply template usage to most experienced C++ programmers.
The thing that is most likely causing your “unexplained” crash is that assignment operator; if you don't define one the compiler will automatically generate one that works as a bitwise copy — almost certainly not what you want if your class is anything other than a collection of simple data types (POD).
For this to work properly on a class of any complexity you will likely need to define a deep copy or use reference counting; in C++ it is almost always a poor choice to let the compiler create any of ctor, dtor, or assignment for you.
And, of course, it would be a good idea to use standard containers rather than the simple array mechanism you implied by your example. In that case you should probably also define a default ctor, a virtual dtor, and a copy ctor because of the assumptions made by containers and algorithms.
If, in fact, you do not want to create a copy of your object but want, instead, to invoke action() on the original object but from within an array, then you will need an array of pointers instead. Again working closely to your original example:
typedef class MyActionableClass T;
T** getGlobalPointer();
void AddInstance(T& objInstance)
{
T** arrayFromElsewhere = getGlobalPointer();
//ok, now at this point we have a reference to an object instance
//and a pointer which we assume is at the base of an array of T **pointers**
//whose first element we don't mind losing
//**reference** the instance we've received by saving its address
arrayFromElsewhere[0] = &objInstance;
//now invoke the action() method on **the original instance**
arrayFromElsewhere[0]->action();
}
Note closely that arrayFromElsewhere is now an array of pointers to objects instead of an array of actual objects.
Note that I dropped the const modifier in this case because I don’t know if action() is a const method — with a name like that I am assuming not…
Note carefully the ampersand (address-of) operator being used in the assignment.
Note also the new syntax for invoking the action() method by using the pointer-to operator.
Finally be advised that using standard containers of pointers is fraught with memory-leak peril, but typically not nearly as dangerous as using naked arrays :-/
I'm surprised it compiles. You declare an array, objectList of 8 pointers to T. Then you assign T[0] = object;. That's not what you want, what you want is one of
T objectList[8];
objectList[0] = object;
objectList[0].action();
or
T *objectList[8];
objectList[0] = &object;
objectList[0]->action();
Now I'm waiting for a C++ expert to explain why your code compiled, I'm really curious.
You can put the object either into a dynamic or a static array:
#include <vector> // dynamic
#include <array> // static
void AddObject(T const & t)
{
std::array<T, 12> arr;
std::vector<T> v;
arr[0] = t;
v.push_back(t);
arr[0].action();
v[0].action();
}
This doesn't really make a lot of sense, though; you would usually have defined your array somewhere else, outside the function.
Yesterday I asked the following question, reproduced here for convenience;
"For one of my projects, what I really wanted to do was this (simplifying it to the bare minimum);
struct Move
{
int src;
int dst;
};
struct MoveTree
{
Move move;
std::vector<MoveTree> variation;
};
I must admit that I assumed that it wouldn't be possible to do this directly, I thought a vector of MoveTree s within a MoveTree would be verboten. But I tried it anyway, and it works beautifully. I am using Microsoft Visual Studio 2010 Express.
Is this portable ? Is it good practice ? Do I have anything to worry about ?"
Basically the answer from the community was no, I couldn't do this, the standard forbids it, so the fact that it works means I am just getting lucky.
So my new question is. How can I implement the simple functionality I want in legal C++, without adding a whole heap of nasty complexity and pain ?
You'll need to use pointers, and dynamic allocation. And you should use smart pointers, to ensure you don't leak anything. boost::shared_ptr allows the type to be incomplete, and therefore this is legal:
std::vector< boost::shared_ptr<MoveTree> > variation;
(I don't know about 0x std::shared_ptr TBH, but it should be the same).
You may use Boost Pointer Container Library. It similar to using std::vector, but the container owns the pointer, so it will destroy the objects.
You may declare it:
#include <boost/ptr_container/ptr_vector.hpp>
struct MoveTree{
Move move;
boost::ptr_vector<MoveTree> variation;
};
Now, if you want to add a new element, you may use:
variation.push_back(new MoveTree());
Now, the container owns the pointer and you get it by reference, for example:
variation[i].move.src = ...
The object is destroyed when the container is destroyed.
I don't have a copy of the C++ standard on-hand, so I can't check the standard, but here's the problem:
Classes cannot contain concrete instances of themselves, even transitively - eg, struct foo { foo x; } is illegal, for obvious reasons. More generally, you cannot reference the size of the structure in any of its members, except the body of member functions.
Classes can contain pointers to themselves - struct foo { foo *x; } is perfectly fine
So the question is, does std::vector define any members (other than member functions) which directly or indirectly depend on sizeof(MoveTree)?
Obviously, std::vector cannot have a static member that is MoveTree itself, as this would imply that an empty vector invokes the MoveTree constructor. However one could envision a std::vector with an aligned char inlineStorage[sizeof(MoveTree)] optimization for one-element vectors. Leaving aside whether this would improve performance, the question at hand is if the standard allows the implementation to take this sort of approach.
That said, it's still a bad idea for a different reason: Because vectors have to copy their elements when resizing their storage, it's a bad idea to have elements with an expensive copy constructor in a vector. Here we have a class whose copy constructor has to recursively recreate the entire tree. It would be better to use a smart pointer class to indirectly reference the child nodes to avoid this overhead:
std::vector<boost::shared_ptr<MoveTree> > variation;
// in C++0x:
std::vector<std::shared_ptr<MoveTree> > variation;
// in C++0x you can also use for lower overhead:
std::vector<std::unique_ptr<MoveTree> > variation;
// you must then use this pattern to push:
variation.push_back(std::move(std::unique_ptr<MoveTree>(new MoveTree())));
If you can use the incomplete type MoveTree as a template parameter in any template, then use one of the solutions in the other answers (e.g. Cat Plus Plus's), or simply use your original solution, add some heavy comments, and do your penance later.
If you can't use it as any template parameter while it is still incomplete, you could use the pimpl idiom to work around this.
By the time the implementation class is defined, the MoveTree class will be complete:
struct Move
{
int src;
int dst;
};
struct MoveTreeImpl;
struct MoveTree
{
Move move;
// Todo: Implement RAII here for the impl
// Todo: Provide impl accessor functions here
private:
MoveTreeImpl* impl;
};
struct MoveTreeImpl
{
std::vector<MoveTree> variation;
};
There are hairy parts to this solution:
Since you're trying to avoid direct instantiation of any template with incomplete types, you'll have to implement RAII manually. You won't get help from std::scoped_ptr<MoveTreeImpl>, as MoveTreeImpl is also incomplete.
What signature do your accessor functions have? Can you return a std::vector<MoveTree>& from an accessor? I'm not sure on this - we're trying to avoid templates that use MoveTree directly. This might be different, because it is not a data member, but I'm not sure :)
Edit:
Reading a bit more, and getting responses from other users, it seems much of this nonsense is unnecessary. It is only the standard containers that have the restriction. You could implement the pimpl with a std:scoped_ptr<MoveTreeImpl>, and I think return std::vector<MoveTree>& from an accessor function, both with no problems.
Use a pointer (or smart pointer) to the type in the Vector, this will be portable. This is because a pointer to a type is complete by just it declaration you don't need the definition.
struct Move
{
int src;
int dst;
};
struct MoveTree;
struct MoveTree
{
Move move;
std::vector<MoveTree*> variation;
};
If you require the type to be managed then use a smart pointer that can handle the delete for you.
Original answer to this question.