Copy consutrctor w/ multiple pointers - c++

I am trying to create a copy constructor for a class with pointer variables. Something is going wrong with the copy construction though, as I segfault when I try to access pointers in my new object...
/* Copy Constructor */
Solver::Solver(const
Solver &obj)
{
// Pointers to use in modified-Midpoint method.
double *m_yTemp1 = new double[CONST_numVariables];
double *m_yTemp2 = new double[CONST_numVariables];
double *m_dTemp = new double[CONST_numVariables];
// Triple pointer to store tableau of data for extrapolation.
double ***m_extrapTableau = new double**[CONST_maxDiv];
*m_extrapTableau = *obj.m_extrapTableau;
for(int i=0; i<CONST_maxDiv; i++)
{
m_extrapTableau[i] = new double*[i+1];
*m_extrapTableau[i] = *obj.m_extrapTableau[i];
for(int j=0; j<=i; j++)
{
m_extrapTableau[i][j] = new double[CONST_numVariables];
*m_extrapTableau[i][j] = *obj.m_extrapTableau[i][j];
}
}
// Pointer of step sizes for extrapolation of modified-Midpoint.
double *CONST_extrap = new double[CONST_maxDiv];
for(int i=0; i<CONST_maxDiv; i++)
{
CONST_extrap[i] = 2.*(i+1.);
}
// Change pointer of new object from already used memory to newly allocated.
*m_yTemp1 = *obj.m_yTemp1;
*m_yTemp2 = *obj.m_yTemp2;
*m_dTemp = *obj.m_dTemp;
*CONST_extrap = *obj.CONST_extrap;
}
My initial questions are:
If I have other non-pointer variables in the class, are they automatically copied or do I need to specify them as well?
How do I deal with passing the address of double or triple pointers? I think I may be doing this wrong.
If CONST_numVariables and CONST_maxDiv are constants set in the class, can they be used in this copy constructor, assuming that they have been set when I copy an object?

The problem with your segfault is here:
double ***m_extrapTableau = new double**[CONST_maxDiv]; // (1)
*m_extrapTableau = *obj.m_extrapTableau; // (2)
In (1) you DECLARE a variable m_extrapTableau LOCAL to your constructor.
But in (2) I can see that you have a class membber with the same name. So the local m_extrapTableau of your constructor will be properly intialised. But it hides the class member that will remain uninitialized for subsequent uses.
About your remaining questions:
1) if you implement a copy constructor, you have to take care of copying everything you need.
2) passing adress of double or tripple pointers requires you to iterate through each level initializing the pointers correctly before using any element of your table. You should consider using vectors of vectors or vectors of vectors of vectors. These a much more easy to initialise, copy, etc...
3) if they are const and you didn't initialize them to another value with a brace initializer they should be usable as such.

Related

How to initialize an array pointer object

I have a little problem to initialize (constructor) an array pointer of object. See the class below. Class test has 2 variable member, a pointer (value) that will be an array, and his size (size); and a constructor with parameters, and a destructor. In main function, I will create an array pointer of objects, and I have problem with it. If I create a single object like:
test obj(4); it will create a object, and his instance, value array is big 4.
Then if i want to create an array of objects:
test *obj;
obj = new test[2]{4,7};
I will create 2 object: obj[0] that is big 4, and obj[1] that is big 7.
So if I want to create more object:
test *obj;
obj=new test[100]{/*here I must write 100 numbers*/}
and this is the problem.
Because I cant write something like this:
test *obj;
obj=new int[100]{4}
I want that each value[] (instance of test class) is big 4, and I wont write 100 times "4".
I thought the analogy of declaring array:
If I write int array[5]={0,0,0,0,0}, I must write 4 times "0", or I can write also:
int array[5]={0} and each value is set to 0. (it's also true that if write int array[5]={5}, first index will be 5 and others 0).
Should I use a default constructor? What should I do?
#include <iostream>
using namespace std;
class test
{
private:
int* value;
int size;
public:
test(int size)
{
this->size = size;
value = new int[size];
}
~test()
{
delete[]value;
}
};
You can allocate the memory on the stack and get rid of dynamic allocation and memory management.
test array[100];
std::fill(std::begin(array), std::end(array), test(100));
Note that you would need a default constructor here.
You can iterate over your pointer to initialize each element
test *obj = new test[100];
for(size_t i = 0; i != 100; ++i)
{
obj[i] = test(/*parameters*/);
/* Remember to provide a move assignment operator
which invalidates the pointer member, otherwise when the
temporary variable is destroyed the new object pointer
member will point to data no more available*/
}
// ...
delete [] obj;
However it would be better to use std::vector
std::vector<test> obj(100, test(/*parameters*/));
Using std::vector your test object is initialized 100 times passing its arguments, using a pointer the allocation (new test[100]) will default construct every element, then you are going to assign each element the new value, that's why std::vector is a better solution to your problem

Auto initialized objects in two-dimensional array?

When I sought for memory leaks I found this interesting peculiarity.
I have
class Perseptron :
public Neiron
{
private:
Neiron** neirons;
}
in header file of class.
When neirons[i][0] initialized then I see in debugger that neirons[i][1,2...n] fields already initialized such values as neirons[i][0] field values before constructor neirons[i][1,2...n] initialization.
neirons = new Neiron*[layerCount];
for (int i=0;i<layerCount;++i)
{
neirons[i] = new Neiron[this->eachLayerCount[i]];
for (int j=0;j<this->eachLayerCount[i];++j)
{
if (i == 0) {
neirons[i][j] = Neiron(2, this->inCount, this->eachLayerCount[i + 1], i, j);
neirons[i][j].inX = this->inX;
}
else if(i!=layerCount-1)
neirons[i][j] = Neiron(2, this->eachLayerCount[i - 1], this->eachLayerCount[i + 1],i,j);
else
neirons[i][j] = Neiron(2, this->eachLayerCount[i - 1], 1,i,j);
}
}
My Neiron constructors:
Neiron::Neiron(int limit,int inCount,int outCount,int layerN,int neironN)
Neiron::Neiron(){}
Why is that?
EDIT
MCVE
class Test{
public:
int fieldA;
Test(int a)
{
fieldA = a;//when a=3, why already fieldA=2 ?
}
Test()
{
}
};
int main()
{
int layers[] = { 3,4,2 };
int counter = 0;
Test** test=new Test*[3];
for (int i = 0;i < 3;++i)
{
test[i] = new Test[layers[i]];
for (int j = 0;j < layers[i];++j)
{
test[i][j] = Test(counter);
counter++;
}
}
for (int i = 0;i < 3;++i) delete[] test[i];
delete[] test;
return 0;
}
Creating object with new always implicitly calls constructor, it's a part of the standard and this approach is quite handy. So writing neirons[i] = new Neiron[this->eachLayerCount[i]]; means "create array with N objects of Neiron class and store pointer to that array into neirons[i]". As a result, dynamic buffer is allocated, N objects are created in it(constructor is called).
Current case doesn't differ much from creating a single object neirons[i] = new Neiron;, where you might get used to implicit constructor calling.
Related part of C++ standard:
Default constructors ... are called to create class objects of dynamic
storage duration (3.7.4) created by a new-expression in which the new-initializer is omitted (5.3.4) ...
EDIT
I might have misinterpreted the question. It looks like you are wondering on some fields being initialized by the time when only default constructor is called, which doesn't do anything on them. There should be no magic, not initialized variable gets its value from the garbage left on dynamic memory. If you see some meaningful values instead of random stuff or zeroes, you might have put your new object into the memory, which has just been freed from being used for the same purpose. If you aren't convinced with this explanation, please create MCVE, so we can reproduce and explain scenario step by step.
EDIT 2
Thanks to clarifications, I see the concern now. Here is what is going within the MCVE:
test[i] = new Test[layers[i]];
Dynamic buffer is allocated and filled with layers[i] objects. Objects are created with default constructor, so their fields aren't initialized, but contain garbage left on the heap (e.g. fieldA of these objects is set to -842150451 or any other meaningless value).
for (int j = 0;j < layers[i];++j)
{
test[i][j] = Test(counter);
counter++;
}
This sample uses anonymous object in the right side, so it is actually an equivalent of this one:
for (int j = 0;j < layers[i];++j)
{
Test temporaryObject(counter);
test[i][j] = temporaryObject;
counter++;
}
Program creates temporary object on stack using parametrized constructor, then initializes test[i][j] with it, destroys temporary object and repeats it for next i/j.
First iteration (i=0, j=0) allocates uninitialized buffer in stack to store temporary object and calls parametrized constructor for it, so you can see fieldA modified in constructor from garbage to zero. Then temporary object is used to init test[i][j] and is destroyed, freeing memory.
Second iteration (i=0, j=1) allocates exactly the same area of memory to store temporary object (you can verify it by inspecting &temporaryObject or checking this in parametrized constructor). Since this memory contains leftovers from previous usage as temporary object, you see constructor changing fieldA from 0 (left from previous iteration) to 1. And so on.
I want to stress, that process above is related to temporary object only. test[i][j] are initialized twice only:
with random garbage during creation with test[i] = new Test[layers[i]];
with actual value from temporary object with test[i][j] = Test(counter);

Copy contents of a unique pointer array in the copy constructor

My class contains a unique pointer to an array. When the copy constructor is called, I want the class to create its own unique pointer array and just copy the contents of the old unique pointer array. I keep getting errors about converting from a const value, and I'm not sure how to get around it.
My pointer is declared under private like this:
std::unique_ptr<Manager[]> managers;
I planned to just loop through the array and copy manually, so I made this copy constructor:
Restaurant::Restaurant(const Restaurant &_r)
{
Manager *_managers = _r.managers;
for (int i = 0; i < MAX_MANAGERS; i++)
{
managers.get()[i] = _managers[i];
}
}
It gives the const convert error on this line:
Manager *_managers = _r.managers;
I just want to make a deep copy. How can I go about it to make this work?
The reason that it won't compile is that
_r.managers is of type std::unique_ptr<Manager[]>, but you want to initialize a raw pointer with this.
just change it to:
Restaurant::Restaurant(const Restaurant &_r)
{
for (int i = 0; i < MAX_MANAGERS; i++)
{
managers.get()[i] = _r.managers.get()[i];
}
}
or first take a smart pointer's data (which is an array)
Manager *_managers = _r.managers.get();
and then you can use it as was before:
for (int i = 0; i < MAX_MANAGERS; i++) {
managers.get()[i] = _managers[i];
}
In the line giving you an error, managers is an std::unique_ptr<Manager[]>. You're trying to assign it to a Manager*, which won't work.
You can fix it by taking the raw pointer of of the unique_ptr, for example:
Manager *_managers = _r.managers.get();
In order to copy the content of unique_ptr<>, you might want to use "deep copy", this means that you write copy constructor in class Manager and a clone function.
Example for copy constructor:
Manager(Manager const& manager) {
name = manager.name;
title = manager.title;
}
clone function:
unique_ptr<Manager> clone() const {
return make_unique<Manager>(*this);
}

Safe to return a vector populated with local variables?

Is it safe to return a vector that's been filled with local variables?
For example, if I have...
#include <vector>
struct Target
{
public:
int Var1;
// ... snip ...
int Var20;
};
class Test
{
public:
std::vector<Target> *Run(void)
{
std::vector<Target> *targets = new std::vector<Target>;
for(int i=0; i<5; i++) {
Target t = Target();
t.Var1 = i;
// ... snip ...
t.Var20 = i*2; // Or some other number.
targets->push_back(t);
}
return targets;
}
};
int main()
{
Test t = Test();
std::vector<Target> *container = t.Run();
// Do stuff with `container`
}
In this example, I'm creating multiple Target instances in a for loop, pushing them to the vector, and returning a pointer to it. Because the Target instances were allocated locally, to the stack, does that mean that the returned vector is unsafe because it's referring to objects on the stack (that may soon be overwritten, etc)? If so, what's the recommended way to return a vector?
I'm writing this in C++, by the way.
Elements get copied when you push_back them into a vector (or assign to elements). Your code is therefore safe – the elements in the vector are no references to local variables, they are owned by the vector.
Furthermore, you don’t even need to return a pointer (and never handle raw pointers, use smart pointers instead). Just return a copy instead; the compiler is smart enough to optimise this so that no actual redundant copy is made.

STL List copies a struct, but the copied values are offset by two memory addresses

I'm compiling using Code::Blocks on Windows 7 using the MinGW compiler (which I can only assume is the latest version; both Code::Blocks and MinGW were installed this past week). My issue crops up under a particular circumstance, and my attempts to write a simpler script that demonstrates the problem have failed (which implies that there is something wrong with my structure). Also, my apologies for how long this post is.
Currently, I'm rolling with one class, FXSDL, which will act as an SDL wrapper:
class FXSDL
{
public:
FXSDL();
virtual ~FXSDL();
int Initialize();
int Render();
FXID CreateCharacter(FXID hRefID, string fpImage, int wpxTile, int hpxTile, map<int, vector<int> > htAnims);
int SetAnim(FXID hRefID, FXID hAnimID);
FXID hPlayer;
protected:
private:
list<FXSurface> m_lstFXObjects;
list<FXSurface>::iterator m_liFirst;
SDL_Surface* m_lpsfSDLScreen;
Uint32 m_tmOld;
Uint32 m_tmFrame;
};
The value type of my list is:
struct FXSurface
{
FXID hRefID;
int wpxTile;
int hpxTile;
int wpxTotal;
int hpxTotal;
int cntTiles;
map<int, vector<int> > htAnims; // All animations
map<int, vector<int> >::iterator vCurr; // Currently active animation
vector<int>::iterator fiCurr; // Currently active frame
SDL_Surface* lpsfSDL;
SDL_Rect* lprcTiles; // Predefined frame positions
string* fpImage;
};
I've implemented very simple initialize and render function. The CreateCharacter function takes a few parameters, the most important of which is htAnims, a map of integer vectors (idea being: I define numeric ids with easy-to-remember representations, such as FXA_IDLE or FXA_WALK, as the key, and the series of number values representing frames for the animation as a vector). This could be fairly easily implemented as a multidimensional integer array, but animations are variable in length and I want to be able to add new anims (or redefine existing ones) without having to recast an array.
The CreateCharacter function is simple. It creates a new FXSurface, populates it with the required data, and pushes the new FXSurface onto the list:
FXID FXSDL::CreateCharacter(FXID hRefID, string fpImage, int wpxTile, int hpxTile, map<int, vector<int> > htAnims)
{
//list<FXSurface>::iterator lpsfTemp;
FXSurface lpsfTemp;
list<FXSurface>::iterator lpsfPos;
SDL_Rect* lprcCurr = NULL;
int cntTileW = 0;
int cntTileH = 0;
int cntCurr = 0;
// Start off by initializing our container struct
//lpsfTemp = new FXSurface();
lpsfTemp.lpsfSDL = IMG_Load(fpImage.c_str()); // Try to load the requested image
if(lpsfTemp.lpsfSDL != NULL) // If we didn't fail to
{
// Assign some variables for tracking
lpsfTemp.hRefID = hRefID;
lpsfTemp.fpImage = &fpImage;
lpsfTemp.wpxTotal = lpsfTemp.lpsfSDL->w;
lpsfTemp.hpxTotal = lpsfTemp.lpsfSDL->h;
// If a tile width was specified, use it
if(wpxTile != 0)
{
lpsfTemp.wpxTile = wpxTile;
lpsfTemp.hpxTile = hpxTile;
} // Otherwise, assume one tile
else
{
lpsfTemp.wpxTile = lpsfTemp.wpxTotal;
lpsfTemp.hpxTile = lpsfTemp.hpxTotal;
}
// Determine the tiles per row and column for later
cntTileW = lpsfTemp.wpxTotal / lpsfTemp.wpxTile;
cntTileH = lpsfTemp.hpxTotal / lpsfTemp.hpxTile;
// And the total number of tiles
lpsfTemp.cntTiles = cntTileW * cntTileH;
lpsfTemp.lprcTiles = new SDL_Rect[cntTileW*cntTileH];
// So we don't calculate this every time, determine each frame's coordinates and store them
for(int h = 0; h < cntTileH; h++)
{
for(int w = 0; w < cntTileW; w++)
{
cntCurr = (h*cntTileW)+w;
lprcCurr = new SDL_Rect;
lprcCurr->w = lpsfTemp.wpxTile;
lprcCurr->h = lpsfTemp.hpxTile;
lprcCurr->x = w*lpsfTemp.wpxTile;
lprcCurr->y = h*lpsfTemp.hpxTile;
lpsfTemp.lprcTiles[cntCurr] = *lprcCurr;
lprcCurr = NULL;
}
}
// Now acquire our list of animations and set the default
//lpsfTemp.htAnims = new map<int, vector<int> >(*htAnims);
lpsfTemp.htAnims = htAnims;
lpsfTemp.vCurr = lpsfTemp.htAnims.find(FXA_WALK_EAST);
lpsfTemp.fiCurr = lpsfTemp.vCurr->second.begin();
this->m_lstFXObjects.push_back(lpsfTemp);
}
else
{
hRefID = 0;
}
return hRefID;
}
It is precisely as the object is pushed that the error occurs. I've stepped through the code numerous times. Initially, I was only able to tell that my iterators were unable to dereference to the FXSurface object. After using watches to identify the exact memory address that the iterator and list objects pointed to, and dereferencing the address, I noticed the reason for my segfaults: all the values which I put into the original FXSurface were pushed down two memory blocks when the list object copied it!
My process for doing this is simple. I set up a breakpoint at the return statement for CreateCharacter, which gives me a view of lpsfTemp (the FXSurface I later add to the list) and m_lstFXObjects (the list I add it to). I scroll through the members of m_lstFXObjects, which brings me to _M_node, which contains the memory address of the only object I have added so far. I add a watch to this address in the form of (FXSurface)-hex address here-
First, find the address:
(There should be a picture here showing the highlighted _M_node attribute containing the list item's address, but I can't post pictures, and I can only post one URL. The second one is by far more important. It's located at http://www.fauxsoup.net/so/address.jpg)
Next, we cast and deference the address. This image shows both lpsfTemp and the copy in m_lstFXObjects; notice the discrepancy?
http://www.fauxsoup.net/so/dereferenced.jpg - See? All the values are in the correct order, just offset by two listings
I had initially been storing fpImages as a char*, so I thought that may have been throwing things off, but now it's just a pointer and the problem persists. Perhaps this is due to the map<int, vector<int> > I store?
FXSDL has a destructor, but no copy constructor and no assignment operator. Yo you're using naked pointers, but violate the Rule of Three.
I'm not going to look any further.
Use smart pointers to manage resources. Do not put a naked resource into a type, except when that type's only intention is to manage this one resource. From another answer given yesterday:
As a rule of thumb: If you have to manually manage resources, wrap each into its own object.
At a glance, I'd say you're double-deleting lpsfSDL and/or lprcTiles. When you have raw pointers in your structure, you need to follow the rule-of-three (implement copy constructor, assignment operator, and destructor) to properly manage the memory.
These lines look wrong to me:
lprcCurr = new SDL_Rect;
lprcCurr->w = lpsfTemp.wpxTile;
lprcCurr->h = lpsfTemp.hpxTile;
lprcCurr->x = w*lpsfTemp.wpxTile;
lprcCurr->y = h*lpsfTemp.hpxTile;
lpsfTemp.lprcTiles[cntCurr] = *lprcCurr;
lprcCurr = NULL;
lpsfTemp.lprcTiles is a SDL_Rect*. lprcTemp.lprcTiles[cntCurr] is a SDL_Rect. You should be writing this, IMHO:
SDL_Rect tmpRect;
tmpRect.w = lpsfTemp.wpxTile;
tmpRect.h = lpsfTemp.hpxTile;
tmpRect.x = w*lpsfTemp.wpxTile;
tmpRect.y = h*lpsfTemp.hpxTile;
lpsfTemp.lprcTiles[cntCurr] = tmpRect;
Dump the lprcCurr entirely.
Now this code:
lpsfTemp.vCurr = lpsfTemp.htAnims.find(FXA_WALK_EAST);
lpsfTemp.fiCurr = lpsfTemp.vCurr->second.begin();
This is bad. These iterators are invalid as soon as the push_back completes. That push_back is making a copy of lpsfTemp. The map and vector members are going to copy themselves and those iterators will copy themselves but they will be pointing to lpsfTemp's members which are going to be destroyed as soon as CreateCharacter exits.
One way to fix that would be to push_back a FXSurface object at the beginning, use back() to get its reference and operate on that instead of lpsfTemp. Then the iterators would stay consistent and they should stay consistent since you are using a list which does not copy its objects around. If you were using a vector or deque or anything other than a list you would need to manage all those pointers and iterators in the copy constructor and assignment operator.
Another thing: Double and triple check your array bounds when you access that lprcTiles array. Any mistake there and you could be scribbling over who knows what.
I don't know if any of that will help you.