C++ vector on heap or stack? - c++

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.

Related

Does delete[] work properly with generic arrays? If so why does using std::vector::erase on it cause error in freeing memory

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.

Using a class member of type 'array'

I know this is a simple question, but I have not been able to find the answer.
I want a C++ class that manages a large block of memory, where the memory is regularly processed in the GPU when a certain class method is called. The class constructor is passed the size of the array, and after construction the array size never changes. The method that does the parallel_for_each should not waste processor cycles or memory when its not necessary.
How do I do this?
I can't create a concurrency::array as a class member, because I need to know how big the array will be before it is created. I can't have a member that is a pointer to a concurrency::array (and then allocate it with 'new' in, for example, the constructor), because I can't figure out how to specify it to the parallel_for_each.
On a side note, I don't normally need to copy the array between the GPU and host, but its fine if for some reason I have to do that, as long as its not done regularly. Otherwise it would waste processor cycles and memory according to the size of the array.
Here's an example of something like what I want. Of course, the reference/pointer captured by the parallel_for_each is wrong. (This is not checked for syntax):
class MyClass
{
int* myHostArrayPtr;
concurrency::array<int,1>* myGpuArrayPtr;
MyClass(int size)
{
myHostArrayPtr = new int(size);
memset(myHostArrayPtr,0,size * sizeof(int));
myGpuArrayPtr = new concurrency::array<int,1>(size,myHostArrayPtr);
}
void ProcessInGpu()
{
parallel_for_each(
myGpuArrayPtr->extent,
[&myGpuArrayPtr](index<1> i) restrict(amp)
{
myGpuArray[i]+=14;
}
);
}
};
I think, you need templates here:
template <std::size_t N> class MyClass {
concurrency::array<int,N> myGpuArray;
...
}
int main () {
MyClass<10> someName;
...
}
OK, I think I figured it out. One must put the parallel_for_each in a function that takes references to the array objects, and then they can be passed by reference to the parallel_for_each. To wit:
void MyClass::Process(concurrency::array<int,1>& myGpuArray){
parallel_for_each(
myGpuArray.extent,
[&myGpuArray](index<1> i) restrict(amp)
{
myGpuArray[i]+=14;
}
);
}
This is interesting because its really a work around to a C++ shortcoming, that you can't refer to a pointed-to variable as a reference without the above function call work-around (I think?). (That is, and not call the copy-constructor).
EDIT:
Yep, the above works. I benchmarked it and its just as fast as the code that uses a local array. Also, I tested it by converting a pointer to a reference in the call, and that worked, too. So it will work with dynamically allocated arrays.

are objects allocated without using "new" allocated on stack or heap

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.

C++ delete class variable from function

class Foo {
// some codes
}
class Bar {
// Constructor, Destructor
vector<Foo*> fooVector;
Foo* getFoo(long index)
{
return fooVector[index];
}
long addFoo(Foo* foo)
{
fooVector.push_back(foo);
return fooVector.size() - 1;
}
void removeFoo(long index)
{
delete fooVector[index];
}
}
This is my codes.
But I want to change removeFoo like
void removeFoo(long index)
{
Foo* foo = getFoo(index);
delete foo;
}
Is it right? I can't sure about this.
In my thought, It may delete foo variable.
Please tell me whether it is right or not.
If the memory for the pointer was allocated by new then yes that's how you free it. However, that won't remove the pointer from the vector, so afterwards your vector have an entry that no longer point to valid memory. You need to erase it from the vector.
Also note that in modern C++ there is seldom a need to use pointers anymore, except for polymorphism really. If you don't have pointers, you don't have to worry about freeing memory or stray pointers.
Using such method you are bypassing most of the benefits you gained from using vector. When removing elements by delete (which is valid in the case you described) you will rubbish your fooVector with non-valid data pointers to some undeclared/invalid memory areas.
It would be handy if, in addition, you showed us how you actually create fooVector elements.
In my opinion, both ways that you presented are valid in C++, but they will lead to hard-to-rely-on results and rubbish in your vector.

Remove classes of a STL::list<class something> which include a dynamic pointer

I have a question and I can't find an answer anywhere. However, there is some code I have to show:
#include "Vector2D"
class something
{
Vector2D * p_Position;
public:
something(){p_Position = new Vector2D;}
~something(){delete p_Position;}
};
int main()
{
std::list<something> Somethinglist;
Somethinglist.push_back(something());
Somethinglist.clear();
return 0;
}
So, this will lead to an assertion fail when it comes to the .clear() function. So I tried out a few things. First of all this code completely works if I just don't put the delete p_Position in the deconstructor. Why is that? Does the STL list .clear() function automatically destroy dynamic Pointers? Or a rather direct question: How can I fix this code?
std::list::push_back() takes its argument by value (i.e. a copy is produced), and that's a real problem because you haven't followed the Rule of Three.
First of all this code completly works if i just don't put the delete p_Position in the deconstructor.
Because p_Position won't be deallocated if you didn't put it in destructor. it causes memory leak.
Why is that. Does the STL list .clear() function automaticly destroy dynamic Pointers?
STL container keeps a copy of original object. when .clear(), these objects will be freed and their destructors will be called.
Or a rather direct question: How can i fix this code?
Follow Rule of Three.
OR use smart pointer
#include <memory>
class something
{
std::unique_ptr<Vector2D> p_Position;
public:
something(){}
~something(){}
};
OR use it without pointer
class something
{
Vector2D p_Position;
public:
something(){}
};