I am new to c++ so question would be elementary.
Lets say I have defined a class Foo and I create a vector of vectors in the following code:
namespace testme {
class Foo {
public:
Foo(int x): x_(x) { };
static vector<vector<int>> ReturnVecOfInts(int num) {
vector<vector<int>> ret(num);
for (int i = 0; i < num; i++) {
vector<int> tmp;
ret.push_back(tmp);
}
return ret;
}
}
When i call:
Foo::ReturnVecOfInts(5)
Is the vector of vectors created on heap or the stack. The reference is on the stack but I want to know whether it points to the heap since i want to return this object from a function.
This is important to me because clearly if these are allocated on the stack the vector of vectors would go out of scope and not usable outside the called function.
You're probably overthinking.
In your case, you're safe in code like this:
Foo f = Bar::GetFoo();
When you return objects from functions, in general, there may occur various optimizations (e.g. RVO, NRVO, etc.), but the bottom line is that your f object is safe to use.
Even if inside Foo you have a data member like std::vector which usually allocates its memory from the heap (you can customize this behavior using custom allocators), thanks to copy constructors, move constructors, destructor, etc. you are totally safe in returning it from functions, or copying Foo instances around.
EDIT I noted that you changed your code after I wrote my answer, returning a vector<vector<int>> instead of Foo. Again, what I wrote still applies.
Related
I was trying to work with arrays that are circular, and so ended up writing a CircularArray class for which I have attached the code. It uses a generic pointer for an array.
When I try creating a list of such circular arrays using std::vector, I face a problem when I try to use erase on it.
I don't see why this should be the case as I think the destructors and copy constructor work well enough normally.
Can someone please help with this?
Code:
CircularArray Class
template<class T> class CircularArray
{
//Class denoted by 'T' is expected to have a functional assignment operator, i.e. operator=(const T& ext) {} in place
protected:
int size=0;
int ori=0;
T* array;
private:
int pos=0;
public:
CircularArray() : CircularArray(0) {}
CircularArray(int s) {size=s;array=new T[s];}
CircularArray(T* ptr,int s)// : CircularArray(s)
{
size=s;array=new T[s];
for(int i=0;i<size;i++)
array[i]=ptr[i];
}
CircularArray(const CircularArray<T>& arr) : CircularArray(arr.size)
{
for(int i=0;i<size;i++)
array[i]=arr.array[i];
}
~CircularArray() {delete[] array;}
...
Testing Code
int main()
{
std::vector<CircularArray<int>> test;
int *a1=new int[3] {1,2,3},*a2=new int[3] {1,2,3},*a3=new int[3] {1,2,3};
CircularArray<int> n1(a1,3),n2(a2,3),n3(a3,3);
test.push_back(n1);
test.push_back(n2);
test.push_back(n3);
test.erase(test.begin()+1);
for(auto v : test)
{
for(int i=0;i<3;i++)
cout << v[i];
cout << "\n";
}
}
This program gives bad output after encountering the deleted part of the vector. Valgrind says that there is a memory corruption in trying to read freed memory.
What is wrong?
Vector elements must be copy/move assignable, yet you are relying on the default copy assignment operator which does not create any fresh memory. Your assigned objects all share the same memory space, later resulting in a double free.
Your constructors are good but you'll need a copy/move assignment operator too.
Read about the Rule of Five.
Also consider just using a std::vector for backing storage; it'll be much simpler.
Does delete[] work properly with generic arrays?
Yes.
Your (implicitly generated) copy and move assignment operator are wrong. They will copy the member pointer. Then you have two pointers to the same array, and one destructor deletes it once, and another deletes it for a second time, which leads to undefined behaviour.
When manually managing dynamic resource, it is essential to keep track of ownership, and make sure that it is released exactly once. A typical solution is to use a smart pointer. Your class has unique ownership (or it would have, if it didn't accidentally share the ownership in the assignment operators) of the dynamic array, so a unique pointer would be an appropriate choice.
On the other hand, you could use a vector container instead of a smart pointer.
I just noticed in my code that I declared a vector on the stack (instead of the heap) and then used my "set"-function to set the member variable of another class to this vector. The only problem is that after exiting my function (myFunction) the vector should be destroyed (because it is on the stack) and the reference to this vector should point to "nothing meaningful". But my code is working correctly and so I was asking myself why. Am I just lucky because the portion of the memory where the vector was, is existing because nobody deleted it until now? So it is a matter of luck if my code is not crashing?
Here is the code:
void myFunction() {
std::vector<std::vector<double>> vDoubleVector = MyUtils::CreateDoubleVector(); //Creates a
double vector (but not on heap)
MyClass mC;
mC.SetDoubleVector(vDoubleVector);
}
class MyClass {
std::vector<std::vector<double>> mDoubleVector;
void SetDoubleVector(std::vector<std::vector<double>>& aDoubleVector) {
mDoubleVector = aDoubleVector;
}
}
Since Luchian was faster than me, I'm going to add sensible improvement to this code:
void SetDoubleVector(std::vector<std::vector<double>> aDoubleVector) {
mDoubleVector = std::move(aDoubleVector);
}
Citing "rule of thumb" - If you need to copy, do it in the interface.
//EDIT to make the answer complete.
Your code did copy the vector by use of its operator= in SetDoubleVector.
There is no reference to the vector, the class has a copy of it.
I am currently trying to get into writing proper C++ code (getting it running was ok for some small prototypes, but it's been ugly).
I recently realized the difference of heap and stack instantiation (O m = new O() vs. O m()).
Now I have a class, where the header file defines a variable, which holds an table definition.
ChunkLoader.hpp:
TablePartion *tablePartial_;
ChunkLoader.cpp:
ChunkLoader() { tablePartial_ = new TablePartial(true, 0, 1); }
Now I want to instantiate the tablePartial on the stack, but I cannot use:
TablePartial tablePartial_(true, 0, 1);
I am totally blind? How can I allocate tablePartial_ on the stack?
Or I am getting it totally wrong, and I cannot use in the constructor since it would be out of scope after the constructor and thus be freed? But since I read that stack variables are better performance-wise, I'd like to use stack instantiation (and getting red of delete).
Main reason: stack overflow told me to get rid of pointers when ever possible. :)
To start off, you should probably avoid the terms "on the stack" or "on the heap", they're implementation details that have nothing to do with the concepts being discussed. Instead, we discuss the lifetime of the object, in terms of automatic (which more or less correlates with the stack), dynamic (which more or less correlates with the heap), static (which more or less correlates with globals), and thread (which is a thread-specific global).
In answer to your specific question, you can use constructor initializers to initialize your variable:
ChunkLoader()
: tablePartial_(true, 0, 1)
{
}
Since the class declaration is:
class MyClass
{
SomeOtherClass x;
};
x is contained in MyClass completely (it's not a pointer to SomeOtherClass).
Ergo, when creating an object MyClass on the stack, x will also be on the stack, and when creating an object MyClass on the heap, x will also be on the heap.
EDIT:
As I understood it, you want to allocate x on the stack. To do this, any instance of MyClass must also be on the stack. For this, you can make the new operator private:
class MyClass
{
SomeOtherClass x;
private:
void* operator new(size_t);
};
If you haven't used the word "new" in C++ (avoiding malloc and other C/OS calls for this conversation), then you haven't dynamically allocated memory on the "heap".
Everything you create in main() and the functions called therein goes on the stack if new isn't used. When you enter a new function call, you get a new stack frame, and all variables declared as so:
void foo() {
int x;
std::string y;
}
are created on the stack.
You can even get a "pointer" to a stack based object so you can use it polymorphically just like a pointer to a heap object:
//These should be "classes" with private/public hiding but I'm being lazy.
struct MyClass {
int x;
virtual void foo();
};
//These should be "classes" with private/public hiding but I'm being lazy.
struct MyClassDerived : MyClass {
void foo() { std::cerr << "foo called!" << std::endl; }
};
int main() {
MyClassDerived x;
MyClass* = &x;
x->foo();
}
It seems that every time I add an object to the vector m_test, the destructor method is called. Am I missing something? How can I prevent this from happening?
class TEST
{
public:
TEST();
~TEST();
int * x;
};
TEST::TEST()
{
}
TEST::~TEST()
{
... it is called every time I push_back something to the vector ...
delete x;
}
vector<TEST> m_test;
for (unsigned int i=0; i<5; i++)
{
m_test.push_back(TEST());
}
The problem here is that you're violating the Rule of Three. Your class has a destructor so you need a copy-constructor and an assignment operator, too. Alternatively, you could not allow your class to be copied (for example by making T(T const&) and T& operator=(T const&) private, or by deriving from boost::noncopyable), and then resize the vector instead of using push_back.
In the first case, you can just push_back your class as you usually would. In the second, the syntax would be something like
std::vector<TEST> vec(5);
// vec now has five default-constructed elements of type TEST.
Not doing either of these things is a bad idea, as you are very likely to run into double deletion issues at some point -- even if you think you'll never copy or assign a TEST where x != nullptr, it's much safer to explicitly forbid it.
By the way, if you have member pointers that should be deleted when an object goes out of scope, consider using smart pointers like scoped_ptr, unique_ptr and shared_ptr (and maybe auto_ptr if you're unable to use Boost or C++11).
It's not called when you push_back, it's called when the temporary is destroyed.
To fix it in your example:
TEST test;
for (int i = 0; i < 5; ++i)
{
m_test.push_back(test);
}
Should only call it once.
Your code is creating a temporary TEST within the loop, using it in push_back, then that temporary is going out of scope when the loop ends/repeats and getting destroyed. That occurs exactly as it should, since the temporary TEST needs cleaned up.
If you want to avoid that, you need to do anything else but make a temporary object for each push. One potential solution is to:
vector<TEST> m_test(5); // Note reserving space in the vector for 5 objects
std::fill(m_test.begin(), m_test.end(), TEST()); // Fill the vector with the default ctor
Depending on how your STL is optimized, this may not need to make multiple copies.
You may also be able to get better handling if you implement a copy constructor in your TEST class, like:
TEST::TEST(const TEST & other)
{
x = new int(*other.x); // Not entirely safe, but the simplest copy ctor for this example.
}
Whether this is appropriate, or how you handle it, depends on your class and its needs, but you should typically have a copy constructor when you have defined your own regular constructor and destructor (otherwise the compiler will generate one, and in this case, it will result in copied and hanging pointers to x).
To avoid destruction of a temporary and to avoid copy constructors, consider using vector::resize or vector::emplace_back. Here's an example using emplace_back:
vector<TEST> m_test;
m_test.reserve(5);
for ( uint i=0; i<5; i++ )
{
m_test.emplace_back();
}
The vector element will be constructed in-place without the need to copy. When vt is destroyed, each vector element is automatically destroyed.
c++0x is required (use -std=c++0x with gnu). #include <vector> is of course also required.
If a default constructor is not used (for example, if the TEST::x was a reference instead of a pointer), simply add arguements to the call to emplace_back() as follows:
class TEST
{
public:
TEST( int & arg) : x(arg) {;} // no default constructor
int & x; // reference instead of a pointer.
};
. . .
int someInt;
vector<TEST> m_test;
m_test.reserve(5);
for ( uint i=0; i<5; i++ ) {
m_test.emplace_back( someInt ); // TEST constructor args added here.
}
The reserve() shown is optional but insures that sufficient space is available before beginning to construct vector elements.
vector.push_back() copies the given object into its storage area. The temporary object you're constructing in the push_back() call is destroyed immediately after being copied, and that's what you're seeing. Some compilers may be able to optimize this copy away, but yours apparently can't.
In m_test.push_back(TEST());, TEST() will create an temporary variable. After the vector copy it to its own memory, the temporary variable is destructed.
You may do like this:
vector<TEST> m_test(5, TEST());
The destructor is not only being called for the temporary variable.
The destructor will also get called when the capacity of the vector changes.
This happens often on very small vectors, less so on large vectors.
This causes:
A new allocation of memory (size based on a growth metric, not just size+1)
Copy of the old elements into the new allocation
Destruction of the elements in the old vector
Freeing of the old vector memory.
Copy construction of the new item onto the end of the new new vector.
See the third answer here:
Destructor is called when I push_back to the vector
I'm not new to programming, but after working in Java I'm coming back to C++ and am a little confused about class variables that aren't pointers. Given the following code:
#include <iostream>
#include <map>
using namespace std;
class Foo {
public:
Foo() {
bars[0] = new Bar;
bars[0]->id = 5;
}
~Foo() { }
struct Bar {
int id;
};
void set_bars(map<int,Bar*>& b) {
bars = b;
}
void hello() {
cout << bars[0]->id << endl;
}
protected:
map<int,Bar*> bars;
};
int main() {
Foo foo;
foo.hello();
map<int,Foo::Bar*> testbars;
testbars[0] = new Foo::Bar;
testbars[0]->id = 10;
foo.set_bars(testbars);
foo.hello();
return(0);
}
I get the expected output of 5 & 10. However, my lack of understanding about references and pointers and such in C++ make me wonder if this will actually work in the wild, or if once testbars goes out of scope it will barf. Of course, here, testbars will not go out of scope before the program ends, but what if it were created in another class function as a function variable? Anyway, I guess my main question is would it better/safer for me to create the bars class variable as a pointer to the map map?
Anyway, I guess my main question is
would it better/safer for me to create
the bars class variable as a pointer
to the map map?
No. C++ is nothing like Java in this and may other respects. If you find yourself using pointers and allocating new'd objects to them a lot, you are probably doing something wrong. To learn the right way to do things, I suggest getting hold of a copy of Accelerated C++ by Koenig & Moo,
The member variable bars is a separate instance of a "dictionary"-like/associative array class. So when it is assigned to in set_bars, the contents of the parameter b are copied into bars. So there is no need to worry about the relative lifetimes of foo and testbars, as they are independent "value-like" entites.
You have more of a problem with the lifetimes of the Bar objects, which are currently never going to be deleted. If you add code somewhere to delete them, then you will introduce a further problem because you are copying the addresses of Bar objects (rather than the objects themselves), so you have the same object pointed to by two different maps. Once the object is deleted, the other map will continue to refer to it. This is the kind of thing that you should avoid like the plague in C++! Naked pointers to objects allocated with new are a disaster waiting to happen.
References (declared with &) are not different from pointers with regard to object lifetimes. To allow you to refer to the same object from two places, you can use either pointers or references, but this will still leave you with the problem of deallocation.
You can get some way toward solving the deallocation problem by using a class like shared_ptr, which should be included with any up-to-date C++ environment (in std::tr1). But then you may hit problems with cyclical pointer networks (A points to B and B points to A, for example), which will not be automatically cleaned up.
For every new you need a corresponding delete.
If you try and reference the memory after you call delete - where ever that is - then the program will indeed "barf".
If you don't then you will be fine, it's that simple.
You should design your classes so that ownership of memory is explicit, and that you KNOW that for every allocation you are doing an equal deallocation.
Never assume another class/container will delete memory you allocated.
Hope this helps.
In the code below you can pass map of Bars and then will be able to modify Bars outside of the class.
But. But unless you call set_bars again.
It is better when one object is responsible for creation and deletion of Bars. Which is not true in your case.
If you want you can use boost::shared_ptr< Bars > instead of Bars*. That will be more Java like behavior.
class Foo {
public:
Foo() {
bars[0] = new Bar;
bars[0]->id = 5;
}
~Foo() { freeBarsMemory(); }
struct Bar {
int id;
};
typedef std::map<int,Bar*> BarsList;
void set_bars(const BarsList& b) {
freeBarsMemory();
bars = b;
}
void hello() {
std::cout << bars[0]->id << std::endl;
}
protected:
BarsList bars;
void freeBarsMemory()
{
BarsList::const_iterator it = bars.begin();
BarsList::const_iterator end = bars.end();
for (; it != end; ++it)
delete it->second;
bars.clear();
}
};
I'm not new to programming, but after working in Java I'm coming back to C++ and am a little confused about class variables that aren't pointers.
The confusion appears to come from a combination of data that is on the heap and data that is not necessarily on the heap. This is a common cause of confusion.
In the code you posted, bars is not a pointer. Since it's in class scope, it will exist until the object containing it (testbars) is destroyed. In this case testbars was created on the stack so it will be destroyed when it falls out of scope, regardless of how deeply nested that scope is. And when testbars is destroyed, subobjects of testbars (whether they are parent classes or objects contained within the testbars object) will have their destructors run at that exact moment in a well-defined order.
This is an extremely powerful aspect of C++. Imagine a class with a 10-line constructor that opens a network connection, allocates memory on the heap, and writes data to a file. Imagine that the class's destructor undoes all of that (closes the network connection, deallocates the memory on the heap, closes the file, etc.). Now imagine that creating an object of this class fails halfway through the constructor (say, the network connection is down). How can the program know which lines of the destructor will undo the parts of the constructor that succeeded? There is no general way to know this, so the destructor of that object is not run.
Now imagine a class that contains ten objects, and the constructor for each of those objects does one thing that must be rolled back (opens a network connection, allocates memory on the heap, writes data to a file, etc.) and the destructor for each of those objects includes the code necessary to roll back the action (closes the network connection, deallocates objects, closes the file, etc.). If only five objects are successfully created then only those five need to be destroyed, and their destructors will run at that exact moment in time.
If testbars had been created on the heap (via new) then it would only be destroyed when calling delete. In general it's much easier to use objects on the stack unless there is some reason for the object to outlast the scope it was created in.
Which brings me to Foo::bar. Foo::bars is a map that refers to objects on the heap. Well, it refers to pointers that, in this code example, refer to objects allocated on the heap (pointers can also refer to objects allocated on the stack). In the example you posted the objects these pointers refer to are never deleted, and because these objects are on the heap you're getting a (small) memory leak (which the operating system cleans up on program exit). According to the STL, std::maps like Foo::bar do not delete pointers they refer to when they are destroyed. Boost has a few solutions to this problem. In your case it's probably be easiest to simply not allocate these objects on the heap:
#include <iostream>
#include <map>
using std::map;
using std::cout;
class Foo {
public:
Foo() {
// normally you wouldn't use the parenthesis on the next line
// but we're creating an object without a name, so we need them
bars[0] = Bar();
bars[0].id = 5;
}
~Foo() { }
struct Bar {
int id;
};
void set_bars(map<int,Bar>& b) {
bars = b;
}
void hello() {
cout << bars[0].id << endl;
}
protected:
map<int,Bar> bars;
};
int main() {
Foo foo;
foo.hello();
map<int,Foo::Bar> testbars;
// create another nameless object
testbars[0] = Foo::Bar();
testbars[0].id = 10;
foo.set_bars(testbars);
foo.hello();
return 0;
}