Constructor in called for allocate memory? - c++

if constructor is used for allocating memory.
In the following program it does not work like that.
See
#include <iostream>
using namespace std;
class Demo
{
int i;
public:
Demo()
{
cout<<"\nDefault contructor called";
}
Demo(int x)
{
i = x;
cout<<"\nParameter contructor called";
}
void Display()
{
cout<<endl<<"i = "<<i<<endl;
}
};
int main()
{
Demo *demo = new Demo[5]; // = {1,2,3,4,5};
int i;
cout<<endl<<endl<<"First time";
cout<<endl<<"Addresses are "<<endl;
for( i=0;i<5; i++)
{
cout<<endl<< &demo[i];
}
cout<<endl<<endl<<"first time assigning values";
for( i=0;i<5; i++)
{
demo[i]= i;
}
cout<<endl<<endl<<"\nAfter first assignment";
cout<<endl<<"Addresses are "<<endl;
for( i=0;i<5; i++)
{
cout<<endl<< &demo[i];
}
cout<<endl<<endl<<"Second time assigning values";
for( i=0;i<5; i++)
{
demo[i]= i+5;
}
cout<<endl<<endl<<" After Second assignment ";
cout<<endl<<"Addresses are "<<endl;
for( i=0;i<5; i++)
{
cout<<endl<< &demo[i];
}
for( i=0;i<5; i++)
{
demo[i].Display();
}
return 0;
}
Output:
Default contructor called
Default contructor called
Default contructor called
Default contructor called
Default contructor called
First time
Addresses are
0x8281008
0x828100c
0x8281010
0x8281014
0x8281018
first time assigning values
Parameter contructor called
Parameter contructor called
Parameter contructor called
Parameter contructor called
Parameter contructor called
After first assignment
Addresses are
0x8281008
0x828100c
0x8281010
0x8281014
0x8281018
Second time assigning values
Parameter contructor called
Parameter contructor called
Parameter contructor called
Parameter contructor called
Parameter contructor called
After Second assignment
Addresses are
0x8281008
0x828100c
0x8281010
0x8281014
0x8281018
i = 5
i = 6
i = 7
i = 8
i = 9
Here the constructor is called three time and the memory address are same, means it is not allocating new memory and uses the same address. Why?
Why is the constructor called more than one time?

When you do this:
demo[i]= i;
i is used to construct a temporary object using the constructor which takes an int. This temporary is then assigned to demo[i]. The assignment does not result in demo[i] being reconstructed as a new object with a different address (objects can't be reconstructed, and can never change their address), it simply results in a memberwise assignment from the members of the temporary to the members of demo[i] (unless you provide an assignment operator which does something different, which you didn't).

Thinking the constructor allocates the memory for your object is a fundamental misunderstanding. When the constructor is called you already have the memory allocated, either on the stack or on the heap. The constructor only prepares this memory for using it afterwards.
However, the constructor is often responsible for allocating further memory for resources used by your object, i.e.
class Container
{
public:
Container()
: ptr_(new int[5])
{}
// ...
private:
int* ptr_;
}

Related

Are class data members initialized before the copy constructor when using the copy constructor?

For example, if I have this class:
class Counter {
public:
int* j = new int[5];
}
A pointer variable is initialized as a data member. If in my copy constructor, I have something like
int* j = new int[7] OR int* j = new int[5](),
therefore initializing the the data member as well, will it create a memory leak for the first one since it wasn't deleted beforehand? Or will the original data member not even initialize?
A default member initializer for a non-static data member will be used in constructors where the same data member is not present in the member initializers list
[...] will it create a memory leak ... ?
Yes.
A default member initializer (DMI) as used in your example:
class Counter {
public:
int* j = new int[5]; // default member initializer for data member 'j'
}
will only be used if, for a given constructor, the data member, here j, is not initialized in the member initializer list of that given constructor.
Thus, if you add a copy constructor to Counter with no member initializer list, the default member initializer for the data member j will be used, and thus you will have a memory leak.
We can study this behaviour by changing the DMI for the data member j into an immediately invoked lambda, to allow us to trace when the DMI is used or not, as well as a dummy copy ctor that simply copies the pointer of the copy-in argument through different means (this is just for this dummy example; see final paragraph regarding lifetime management as well as deep-copying vs shallow-copying):
#include <iostream>
struct Counter {
int* j = []() {
std::cout << "Calling DMI for j.\n";
auto p = new int[5];
return p; }();
// Uses the DMI for member 'j'.
Counter() {}
// Uses the DMI for member 'j'.
Counter(const Counter& c) { j = c.j; } // Memory leak.
};
int main() {
Counter c1; // Calling DMI for j.
Counter c2 = c1; // Calling DMI for j.
// Delete resource common for c1 and c2.
delete c2.p; // A rogue resource from c2 construction was leaked.
}
If your either perform the copying into the j data member in a member initializer list of the copy constructor:
#include <iostream>
class Counter {
public:
int* j = []() {
std::cout << "Calling DMI for j.\n";
auto p = new int[5];
return p; }();
// Uses the DMI for member 'j'.
Counter() {}
// Does not use the DMI for data member 'j'.
Counter(const Counter& c) : j(c.j) { }
};
int main() {
Counter c1; // Calling DMI for j.
Counter c2 = c1;
// Delete resource common for c1 and c2.
delete c2.p; // OK, no resources leaked.
}
or simply explicitly set the data member j to nullptr as part of a member initializer list in the copy ctor:
#include <iostream>
class Counter {
public:
int* j = []() {
std::cout << "Calling DMI for j.\n";
auto p = new int[5];
return p; }();
// Uses the DMI for member 'j'.
Counter() {}
// Does not use the DMI for data member 'j'.
Counter(const Counter& c) : j(nullptr) { j = c.j; }
};
int main() {
Counter c1; // Calling DMI for j.
Counter c2 = c1;
// Delete resource common for c1 and c2.
delete c2.p; // OK, no resources leaked.
}
you will be overriding the DMI for the data member j.
Note that you will need to take extra care when implementing manual memory management in terms of raw C-style pointers, which is a very common recipe for lifetime issues. If possible, instead rely on smart pointers such as std::unique_pointer or std::shared_pointer to avoid lifetime issues; this is, however, out of scope for this question. Note, also that in the contrived examples above, the copy constructor will be shallow-copying the int resource to which the j data member pointer of the copy-in argument points (and likely owns). For implementing a real case copy constructor, you likely want to deep-copy this resource.
The construction instantiation int* j = new int[5]; will trigger if there are no overwrites on it.
Let me give an example:
class Counter {
public:
Counter(int x) {}; // j will be initialized as int* j = new int[5];
Counter(double y) : j(nullptr) {}; // the line j = new int[5]; won't be invoked. instead j = nullptr;
int* j = new int[5];
}
By default copy constructor overwrites it by copying j.
So if you explicitly write copy constructor like
Counter(const Counter& c) : j(c.j) {};
it will work properly. But if you write it like
Counter(const Counter& c) {j=c.j;};
it will cause a memory leak.

c++ Constructor behavior

i'm newbie in c++ languge, and i'm fimiliar with java language.
in Java world, the code looks ok , but not in c++.
can someone please explain why the both constructors are called?
class Position {
public:
Position(void)
{
std::cout<<"defualt constructor\n";
}
Position(unsigned int row,unsigned int col)
{
std::cout<<"two Arguments constructor\n";
row_index = row;
col_index = col;
}
private:
unsigned int row_index;
unsigned int col_index;
};
class Tool
{
public:
Tool(char Team,unsigned int row,unsigned int col)
{
pos = Position(row,col);
team = Team;
}
std::string To_string()
{
std::string str = "team: ";
str+= team;
str+= " pos: ";
str+= pos.To_string();
return str;
}
char Get_team()
{
return team;
}
private:
Position pos;
char team; // A or B
};
int main(void)
{
Tool t = Tool('A',1,3);
return 0;
}
i intended to call for the two arguments constructor
OUTPUT:
defualt constructor
two Arguments constructor
In the Tool class the Position object is first default constructed before the execution of the Tool constructor body is executed. Then you create a new temporary Position object in the Tool constructor body, and use it to assign to pos.
The important part here is that object construction is a three-step process:
The object is allocated
The object is initialized and all its members are constructed (here the Position default constructor is called)
The constructor of the object is executed (here the two-argument Position constructor is called)
To only use the two-argument Position constructor, and not simply assign to the pos object, you need to use an constructor initializer list. You do this by modifying the Tool constructor as this:
Tool(char Team,unsigned int row,unsigned int col)
: pos(row, col), // Initializes the `pos` object
team(Team) // Initialize the `team` member
{
// No code needed, the members have already been initialized
}
In C++, all member variables are constructed before the body of the constructor is entered. Your code default automatically constructs a Position, and then in the body of the constructor creates another Position and assigns it to the previously constructed one.
You need to pass the parameters of Position using an initialisation list:
Tool(char Team,unsigned int row,unsigned int col) : pos( row, col ), team(Team) {
// constructor now empty
}
In general, the body of a constructor should be empty.
When the execution enters constructor body, member objects, of the owning class, need to be constructed (default constructor is used, if no explicit call to constructor is specified).
Upon entering the constructor body, Position(row,col) in pos = Position(row,col); creates a temporary Position object, which gets assigned to pos.
If you want to avoid calling default constructor, of member objects, in such a case, use initialize members in an initializer-list:
Tool(char Team,unsigned int row,unsigned int col)
: pos (row, col), team (Team)
{
}
Why the code, in Java, works, as you expect, is due to the fact, that you, always, operate on references to objects, rather than on objects, as values. And non-initialized member object references in Java, would be default initialized to null (if memory serves right), until you create an object, and assign a reference to it, to a member variable.

Conversion constructor clarification

#include<iostream>
using namespace std;
class Test
{
private:
int x;
public:
Test(int i)
{
cout<<"Conversion constructor called..."<<endl;
x = i;
}
~Test()
{
cout<<"Destructor called..."<<endl;
}
void show()
{
cout<<" x = "<<x<<endl;
}
};
int main()
{
Test t(20);
t.show();
t = 30;
t.show();
return 0;
}
output:
Conversion constructor called...
x = 20
Conversion constructor called...
Destructor called...
x = 30
Destructor called...
When i am doing t = 30 why it is calling constructor and destructor?
Please explain.Many thanks in advance.
There is no overload of = that can be used to assign directly from an int value. Your conversion constructor allows 30 to be converted to a Test object, which can then be assigned using the implicitly-generated copy constructor (which copies each member). So your assignment is equivalent to
t = Test(30);
creating and destroying a temporary object to assign from.
You could avoid this by providing an assignment operator:
Test & operator=(int i) {x = i;}
in which case the assignment could use this directly, equivalent to
t.operator=(30);
When you write t = 30, your compiler creates a temporary Test variable, which it creates using the conversion constructor. After setting t equal to this temporary variable, the temporary variable is then destroyed, calling the destructor.
Because t is already defined, it cannot be initialized throug the convertion contructor.
Instead, it creates a temporay Test object, calls the operator=, then delete it.
"why it is calling constructor and destructor?"
Because there's a (implicit) temporary instance of Test constructed, assigned to t and destructed after assignment.

My Stats class prints garbage

Consider the following class:
class Stats
{
private:
int arraySize; // size of array
int * data; // pointer to data, an array of integers
// default size of array in default constructor
static const int DEFAULT_SIZE = 10;
public:
Stats() // default constructor
{
arraySize = DEFAULT_SIZE; // element count set to 10
data = new int[DEFAULT_SIZE]; // array of integers
srand((unsigned int) time(NULL)); // seeds rand() function
// initializes integer array data with random values
for (int i = 0; i < DEFAULT_SIZE; i++)
{
// data filled with value between 0 and 10
data[i] = rand() % (DEFAULT_SIZE + 1);
}
}
~Stats() // destructor that deletes data memory allocation
{
delete [] data;
}
void displaySampleSet(int numbersPerLine)
{
cout << "Array contents:" << endl; // user legibility
// iterates through array and prints values in array data
for (int i = 0; i < arraySize; i++)
{
cout << data[i];
/* nested if statements that either prints a comma between
values or skips to next line depending on value of numbersPerLine */
if (i + 1 < arraySize)
{
if ((i + 1) % numbersPerLine != 0)
cout << ", ";
else
cout << endl;
}
}
}
}
For some reason, when I create a Stats object in the following way:
Stats statObject = Stats();
and then call the displaySampleSet() on it, the numbers display fine. However, the function prints garbage when the Stats object is created in the following way:
Stats statObject;
statObject = Stats();
I have no idea why it does this and have a feeling it has to do with the integer pointer 'data' and/or with the way the object is being created but I'm not sure what... Any and all help is fully appreciated! Thank you so much in advance.
Update: Destructor added
Both the code statements produce undefined behavior. It is lucky that the first one works while second doesn't.
Stats statObject = Stats();
Is copy initialization. It copies the created Stats object by calling the default constructor and then copies it in to statObject by calling the copy constructor. Note your class does not provide an copy constructor so the implicitly generated one gets used. This creates a shallow copy of the dynamically allocated members. The object from which this copy gets created is eventually destroyed and then whats left in your class is dangling pointers which do not point to anything valid. The copy constructor needs to do a deep copy.
Same is the case with:
Stats statObject;
statObject = Stats();
Wherein the compiler generated copy assignment operator is called. Resulting in similar problems as in case 1.
You need to follow the Rule of Three and provide your copy constructor and copy assignment operators for the class.
You code is using synthesized copy constructor , assignment operator defined by compiler.
Also you are not freeing the memory allocated dynamically for default constructor.
you have to define your own copy construcor, overload assignment operator( follow rule of three).
Both the cases are undefined behaviour
Stats statObject;
statObject = Stats(); //using compiler defined assignment operator.
Stats statObject = Stats(); //using compiler defined copy constructor.
Here temp object generated is is using assignment operator overloaded by compiler and is doing shallow copy instead of deep copy.
overload assignment operator:
Stats& operator=(const Stats& rhs);
define copy constructor:
Stats(const Stats& rhs);

Why do I have to provide default ctor?

Why do I have to provide default ctor if I want to create an array of objects of my type?
Thanks for answers
Because they have to be initialized.
Consider if it wasn't the case:
struct foo
{
foo(int) {}
void bar(void) {}
};
foo a[10];
foo f = a[0]; // not default-constructed == not initialized == undefined behavior
Note you don't have to:
int main(){
// initializes with the int constructor
foo a[] = {1, 2, 3};
}
// if the constructor had been explicit
int main(){
// requires copy-constructor
foo a[] = {foo(1), foo(2), foo(3)};
}
If you really need an array of objects and you can't give a meaningful default constructor, use std::vector.
If you really need an array of of objects, can't give a meaningful default constructor, and want to stay on the stack, you need to lazily initialize the objects. I have written such a utility class. (You would use the second version, the first uses dynamic memory allocation.)
For example:
typedef lazy_object_stack<foo> lazy_foo;
lazy_foo a[10]; // 10 lazy foo's
for (size_t i = 0; i < 10; ++i)
{
// create a foo, on the stack, passing `i` to the constructor
a[i].create(i);
}
for (size_t i = 0; i < 10; ++i)
a[i].get().bar(); // and use it
// automatically destructed, of course
The default constructor will be called for each object in the array.
You don't have to specify a default constructor as one will be created for you.
Just make sure you don't declare a constructor with no parameters as private or protected.
Here's an example of one being created for you:
class C
{
};
C c[10];
Whereas if you make it private you get a compiling error:
class C
{
private:
C()
{
}
};
C c[10];
When defining an array, you cannot specify ctor parameter, hence every object in the array must be constructed using the default ctor.
Normally, the C++ compiler will create the default ctor for you automatically. But, if you define a ctor with parameters, then the automatically creation of the default ctor is supressed, and you must explicitly write one.
Because when the array is initialized, default constructors are called for its items.