Auto initialized objects in two-dimensional array? - c++

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);

Related

C++ value initialize items of a custom container

Lets take custom vector implementation as an example:
template<typename Object>
class myVector {
public:
explicit myVector(int size = 0) :
_size{ size },
_capasity{ size + SPARE_CAPACITY }
{
_buff = new Object[_capasity];
if (_size > 0) {
for (int i = 0; i < _size; i++) {
//_buff[i] = 0;
}
}
}
// more code
private:
Object * _buff = nullptr;
int _size;
int _capasity;
};
So my question is, how to make myVector be value-initialized in case I'll initialize it as:
int main() {
myVector<int> v02(5);
}
Here, it contains 5 int values, so I need it to be all zeros; same with other types. I commented out _buff[i] = 0; as it's specific to int. Please give me some hints.
It's as simple as
for (int i = 0; i < _size; i++)
_buff[i] = Object{};
Alternatively, you could get rid of the loop and add a pair of {} (or ()) here:
_buff = new Object[_capasity]{};
// ^^
But this option would value-initialize all _capasity objects, rather than the first _size ones, as noted by #bipll.
Also, note that if you want to mimic the behavior of std::vector, you need to allocate raw storate (probably std::aligned_storage) and call constructors (via placement-new) and destructors manually.
If Object is a class type, _buff = new Object[_capasity]; calls default constructors for all _capasity objects, rather than for the first _size objects as std::vector does.
Note that when calling
_buff = new Object[_capasity];
(btw, why have you moved this initialization out of init-list, into constructor body?) you already have default-initialized _capasity objects. Default initialization has the following effects here: while elements of scalar type would remain uninitialized (and reading from them UB), for class types you have already called _capasity constructors.
To avoid unnecessary constructions you have the following possible options, among others:
Use std::aligned_alloc to allocate non-initialized memory:
explicit myVector(std::size_t size = 0) :
size_{ size }
, capacity_{ size + SPARE_CAPACITY }
, buff_{std::aligned_alloc(alignof(Object), _capacity)}
{
if(!buff_) throw std::bad_alloc();
if(size) new (buff_) Object[size]{}; // empty braces answer your original query
}
Remember that again buff_ should be aligned_alloced when vector grows (can be std::realloc()ed for trivial types), and in destructor it should be std::free()d — and prior to that size_ objects inside it should be destructed (with an explicit call to ~Object()).
Change buff_'s type to something more trivial yet properly aligned:
using Storage = std::aligned_storage_t<sizeof(Object), alignof(Object)>;
Storage *buff_;
Object *data_ = nullptr;
public:
explicit myVector(std::size_t size = 0) :
size_{ size }
, capacity_{ size + SPARE_CAPACITY }
, buff_{new Storage(_capacity)}
{
if(size) data_ = new (buff_) Object[size]{};
}
Again, in destructor, objects should be manually destroyed, but this time buff_ can be simply delete[]d afterwards.

What is the difference between declaring an object outside and inside of a loop

I was wondering, what is the difference if any between these two ways of using an object obj. And what will happen to the memory in both examples?
Example 1: Object is declared outside of the loop
Example 2: Object is declared inside of the loop.
In both example I call function func which takes as parameters a vector of type float. The dimension of this vector is no less than 9000 elements.
Example 1
MyObject obj;
for(int i = 0; i < n; i ++)
{
obj.func(vector<float>);
}
Example 2
for(int i = 0; i < n; i ++)
{
MyObject obj;
obj.func(vector<float>);
}
When you declare the object inside the loop, a new object will be created on each iteration and the exising one destroyed at the end of each iteration. This is because the object will have a scope inside the {}.
When you declare it outside, a single object is created and you work with that, But when you put it inside a loop, a new object is created and destroyed on each iteration, which will affect the speed.
That is, when you use
MyObject obj;
for(int i = 0; i < n; i ++)
{
obj.func(vector<float>);
}
you crate only one object. But when you use
for(int i = 0; i < n; i ++)
{
MyObject obj;
obj.func(vector<float>);
}
you create and destroy n objects. That will increase the execution time. So, it's better to use the first.

Copy consutrctor w/ multiple pointers

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.

Assignment overloading: why does using the same object cause problems in the program?

Suppose we have the following:
class StringClass
{
public:
...
void someProcessing( );
...
StringClass& operator=(const StringClass& rtSide);
...
private:
char *a;//Dynamic array for characters in the string
int capacity;//size of dynamic array a
int length;//Number of characters in a
};
StringClass& StringClass::operator=(const StringClass& rtSide)
{
capacity = rtSide.capacity;
length = rtSide.length;
delete [] a;
a = new char[capacity];
for (int i = 0; i < length; i++)
a[i] = rtSide.a[i];
return *this;
}
My question is: why does this implementation of overloading the assignment operator cause problems when we try to assign an object to itself like:
StringClass s;
s = s;
The textbook I'm reading (Absolute C++) says that after delete [] a; "The pointer s.a is then undefined. The assignment operator has corrupted the object s and this run of the program is probably ruined."
Why has the operator corrupted s? If we're reinitalizing s.a right after we delete it, why does this cause such a problem in the program that we have to redefine the function as:
StringClass& StringClass::operator=(const StringClass& rtSide)
{
if (this == &rtSide)
//if the right side is the same as the left side
{
return *this;
}
else
{
capacity = rtSide.capacity;
length = rtSide.length;
delete [] a;
a = new char[capacity];
for (int i = 0; i < length; i++)
a[i] = rtSide.a[i];
return *this;
}
}
If you are assigning an object to itself both a and rt.a point to the same string, so when you do delete [] a you are deleting both what a and rt.a point to; then you do reallocate it, but the data you were going to copy (on itself) in the loop has been lost in the delete.
In the loop now you will just copy whatever junk happens to be in the memory returned by new on itself.
By the way, even with the "safety net" of the self-assignment check that assignment operator isn't completely ok (for instance, it's not exception safe); the "safe" way to define the "big three" (copy constructor, assignment operator, destructor) is using the "copy and swap idiom".
If you self-assign, you free (delete) the string via the LHS argument before you copy it to the newly allocated space via the RHS argument. This is not a recipe for happiness; it is undefined behaviour and anything may happen. A crash is plausible; if you're really unlucky, it may appear to work.
Consider what the value of rtSide.a is when you're inside the broken operator=.
It's the same as this->a, the values you just clobbered. Accessing non-owned memory is undefined behavior, thus accessing this->a is undefined behavior (since you just freed it).
delete [] a;
a = new char[capacity];
for (int i = 0; i < length; i++)
a[i] = rtSide.a[i]; //Invalid when this->a == rtSide.a
//because rtSide.a is no longer owned by your program.
If you did actually want to do this, you would have to make a copy of a before deleting it:
char* ca;
if (this == &rtSide) {
ca = copy of rtSide.a or this->a;
} else {
ca = rtSide.a;
}
//Do your assigning and whatnot
if (this == &rtSide) {
delete[] ca;
}
Obviously it's much more efficient to just do nothing instead of making temporary copies of all of an instances own members. It's the same concept as doing int x = 5; int y = x; x = y;
It is because you've first deleted the pointer delete [] a;
and then later on trying to copy from the deleted location:
for (int i = 0; i < length; i++)
a[i] = rtSide.a[i]; //rtSide has already been deleted as 'this' and '&rtSide' are same.
Remember it is the same location you are trying to copy from, which you've already deleted.
Hence, the error!
The later code you posted fixes this problem by checking for self-assignment as a separate case.
delete [] a;
a = new char[capacity];
for (int i = 0; i < length; i++)
a[i] = rtSide.a[i];
That's why. Think of it like this:
You delete whatever a points to, then allocate a new chunk of memory. The new chunk of memory contains garbage which becomes your new data. Do not be confused by the loop that does a[i] = rtSide.a[i]; that only copies the garbage onto itself.
Remember, this and rtSide both lead you to the same object. When you modify the object using this the object that rtSide refers to is modified.

Return value to class object in C++

I have a header file:
using namespace std;
class IntList{
private:
int *Intl;
int Capacity;
int Count;
public:
IntList(int capacity){
Capacity = capacity;
Count = 0;
Intl = new int[capacity];
}
~IntList(){
delete Intl;
}
//adds the integers of the specified collection to the end of the List; return false if the new Count will be greater than Capacity
bool AddRange(const IntList &items){
//int *Temp = items.;
if(items.Count > Capacity - Count){
return false;
}else{
for(int i = 0; i <items.Count; i++){
Intl[Count] = items.Intl[i];
Count++;
}
return true;
}
}
};
But I don't know why I can't return value to IntList object in there:
//creates a copy of a range of elements in the source List
IntList GetRange(int index, int count){
IntList A(count);
for(int i = 0; i < count; i++){
A.Intl[i] = Intl[index -1 +i];
}
return A;
}
I want to return value of A whose type is IntList but I meet an error on "_BLOCK_TYPE_IS_VALID(pHead->nBlockUse) in visual studio 2010. How can I repair it?
Because int *Intl; is an object you manually manage, you'll need to implement the copy constructor for your class.
The function GetRange returns by value. The local object A gets destroyed, and its member Intl gets deleted in the destructor, so your copy (as copied by the default copy constructor) is only a shallow one, and will contain an invalid member.
EDIT: As Rob correctly pointed out, you'll also need to implement the assignment operator (you already have a destructor).
For an object which is returned by value makes a call to copy-constructor . You must make a copy-constructor and define it so that you get appropriate results. Returning by reference actually does not require call to copy constructor but should not be made for a temporary object. Also since you have a pointer type as member variable in class . It would be appropiate for you to overload the = operator. It should be define properly to avoid memory leak. Do something like this Intlist a=GetRange(index,count) . Also you should create a copy constructor for this . Your code also has a bug that it doesnot overload= operator for class Intlist .
you can write a copy constructor something like this :-
Intlist::Intlist(const Intlist& cSource)
{
capacity = cSource.capacity;
count= cSource.count;
// Intl is a pointer, so we need to deep copy it if it is non-null
if (cSource.Intl)
{
// allocate memory for our copy
Intl = new int[capacity];
// Copy the Intl into our newly allocated memory in for loop
for(i=0;i<capacity;i++)
{
// copy part
}
}
else
intl = NULL;
}
Just an e.g how you should write it.