constructor called in main, but object not created properly - c++

I am trying to call the constructor H, but for some reason its not being called.
I get no error when I compile my code, and I get the output:
A object initialized.
H object initialized.
If H was initialized properly, the cout from the constructor should also be shown.
Can someone please help? Thank you.
I also have another question. How can I change the value of hVec[i].a and have the value of
aArray[i].a take upon this value as well? I know I am suppose to use pointers, but an very confused. Sorry for all the questions; I'm reltaively new to programming in C++.
#include <vector>
#include <iostream>
struct A
{
A(int av):a(av){}
int a;
};
struct Heap
{
Heap(std::vector<A> hVal)
{
std::cout << "Constructor for H object. \n";
for (int i=0; i<hVal.size(); ++i)
{
hVec.push_back(hVal[i]);
std::cout << "hVec[i].a = " << hVec[i].a << " ";
}
std::cout << std::endl;
}
std::vector<A> hVec;
};
int main()
{
A a0(2), a1(4), a2(8);
std::vector<A> aArray;
aArray.push_back(a0);
aArray.push_back(a1);
aArray.push_back(a2);
std::cout << "A object initialized. \n";
Heap h(A);
std::cout << "H object initialized. \n";
return 0;
}

Your struct Heap does not have a constructor which takes A as argument.
However, you can initialize h with aArray which is std::vector<A> type
Heap h(aArray);
In C++, unless you are trying to be compatible with C, otherwise just use class instead of struct

Heap h(A);
This declares a function of type Heap(A) named h. Perhaps you meant:
Heap h(aArray);
This declares a local variable of type Heap named h.

use Heap h(aArray); instead of Heap h(A);
The line Heap h(A); declares a function h taking an object of type A as parameter, and returns an object Heap.

Related

Why is defining the type of a pointer causing issues in my code?

When initializing a pointer to allocate memory in the heap, should we specify the type as a pointer? That is, should it be:
int* ptr = new num;
OR
ptr = new num;
Both seem to work, and I was under the impression that the first method is better, but doing it is causing some issues in my code below.
I have a class with two member variables, both of which should be pointers to a new int on the heap. When the copy constructor is invoked, it should allocate new memory in the heap, but copy the values of the ints to which the pointers of the argument being passed in are pointing.
#include <iostream>
using namespace std;
// Header file
#pragma once
class numPair {
public:
int *pa,*pb;
numPair(int, int);
numPair(const numPair &);
};
// Implementation file
#include "Cube.h"
#include <iostream>
using namespace std;
numPair::numPair(int a, int b) {
cout << "Constructor invoked!" << endl;
int* pa = new int(a);
cout << "pa = " << pa << endl;
cout << "*pa = " << *pa << endl;
int* pb = new int(b);
cout << "pb = " << pb << endl;
cout << "*pb = " << *pb << endl;
}
numPair::numPair(const numPair& other) {
cout << "Copy invoked!" << endl;
int* ptr = other.pa;
cout << "ptr in copy: " << ptr << endl;
}
// main.cpp file
#include "Cube.h"
#include <iostream>
using namespace std;
int main() {
numPair p(15,16);
cout << "p.pa = " << p.pa << endl;
numPair q(p);
numPair *hp = new numPair(23, 42);
delete hp;
return 0;
}
The output of the main.cpp file is:
Constructor invoked!
pa = 0x5594991a7280
*pa = 15
pb = 0x5594991a72a0
*pb = 16
p.pa = 0x3
Copy invoked!
ptr in copy: 0x3
Constructor invoked!
pa = 0x5594991a72e0
*pa = 23
pb = 0x5594991a7300
*pb = 42
As can be seen, when the constructor is invoked, the pa and pb are both valid memory addresses to ints holding the values 15 and 16. However, once the constructor has finished executing, if I try to access the value of p.pa, it returns 0x3, instead of the memory address from before. This is, of course, a problem on its own and also leads to issues with the copy constructor.
I've found two ways of fixing this.
The first is to change the definition of the constructor by removing the type of pa and pb. That is changing int* pa = new int(a); to pa = new int(b). Repeat the same for pb. Now, p.pa returns the correct memory address.
The second is by commenting out the initialisation and deletion of hp. That is, removing these lines from the main() function:
numPair *hp = new numPair(23, 42);
delete hp;
I don't really understand why specifying the type of a pointer is causing these errors or, in fact, why the memory addresses for p.pa and p.pb are having errors because of the initialization of another instance of the class, especially when considering the fact that hp is initialized after p.
The short answer is that you are misunderstanding the distinction between locally scoped variables and class members. One way to think about this is that you only need to tell your program the type of an identifier once.
In your class definition you declare two pointers using the type int (int *pa,*pb), but in your constructor numPair::numPair(int a, int b) you are creating two new pointer declarations (int* pa and int* pb) that only exist within the constructor. From within your class constructor, you can reference its members by name without declaring a type every time, since you already declared them in the class definition. This is why your solution #1 works for you.
Additionally, in your original code, you are leaking the memory allocated on the heap for the values because you do not call delete on those pointers.

Compiler: How is class instantiation code compiled?

Assume we have (in C++): MyClass* x = new MyClass(10)
Can someone please explain what 'exactly' happens when compiler parses this statement? (I tried taking a look at the Red Dragon book but couldn't find anything useful).
I want to know what happens in the stack/heap or compiler's symbol table. How compiler keeps track of the type of x variable? How later calls to x->method1(1,2) will be resolved to appropriate methods in MyClass (for simplicity assume there is no inheritance and MyClass is the only class that we have).
MyClass* x is a definition of pointer to object (instance) of type MyClass. Memory for that variable is allocated according to the place of its definition: if it is defined in the method, and is a local variable, stack is used. And it is memory to store the address.
Then expression new MyClass(10) is a command to allocate memory in heap for an object (instance) itself and return address to be stored in x. To fill the memory of new object MyClass (set up its initial state) special method (at least one) is executed automatically - constructor (or several in some cases) - that receives value 10 in your example.
Because C++ allows inheritance (this is also the reason for the execution of several constructors when an instance created) there are some mechanism to determine which method should be exactly called. You should read somewhere about Virtual method table.
In the simplest case (without inheritance), type of variable x (pointer to object of type MyClass) provide all necessary information about object structure. So, x->method1(1,2) or (*x).method1(1,2) provide call of member method1 to execute it with parameters 1 and 2 (stored in stack) as well as with data that form the state of object (stored in heap) and available by this pointer inside any non-static member of class. The method itself, of course, not stored in the heap.
UPDATE:
You can make example to make same experiments, like:
#include <iostream>
#include <string>
using namespace std;
class MyClass
{
private:
int innerData;
long long int lastValue;
public:
MyClass() // default constructor
{
cout << "default constructor" << endl;
innerData = 42;
lastValue = 0;
}
MyClass(int data) // constructor with parameter
{
cout << "constructor with parameter" << endl;
innerData = data;
lastValue = 0;
}
int method1(int factor, int coefficient)
{
cout << "Address in this-pinter " << this << endl;
cout << "Address of innerData " << &innerData << endl;
cout << "Address of lastValue " << &lastValue << endl;
cout << "Address of factor " << &factor << endl;
lastValue = factor * innerData + coefficient;
return lastValue;
}
};
int main(void)
{
MyClass* x = new MyClass(10);
cout << "addres of object " << x << endl;
cout << "addres of pointer " << &x << endl;
cout << "size of object " << sizeof(MyClass) << endl;
cout << "size of pointer " << sizeof(x) << endl;
x->method1(1, 2);
}
C++ is indeed a bit nasty, and this already started in C. Just look at the first 3 tokens : MyClass * x. The compiler has to look up MyClass to determine that this is not a multiplication. Since it is a type, it shouldn't look up x either, but add x to the symbol table right there (really can't be delayed). In the ideal world of simple-to-parse languages, there would be no need to keep the symbol table up to date for every token parsed.
After the definition of x, the = signals an initializing expression. That's an easy one to parse: new is unambiguously a keyword, it's not a placement new and the type being created is right there.

C++ - Scope of Variables Created in a Class Method

I'm trying to learn C++, and from my understanding if a variable goes out of scope then it is destroyed and its memory is reallocated. If I have a class and it's method creates a variable, shouldn't that variable be destroyed after the method call? For example:
class TestClass {
public:
struct Pair{
std::string name;
int value;
};
void addPair() {
//should be deleted after push_back is called?
Pair x = Pair{ std::string{ "Test Object " }, counter++ };
pairs.push_back(x);
}
void printPairs() {
for (int i = 0; i < pairs.size(); i++) {
std::cout << "pair { " << pairs[i].name << " : " << pairs[i].value << " } " << std::endl;
}
}
void removePair() {
pairs.pop_back();
}
private:
int counter;
std::vector<Pair> pairs;
};
But when I tried addPair() then printPairs() then removePair() it works fine. Why doesn't it throw an error saying invalid access to memory location?
You said:
from my understanding if a variable goes out of scope then it is destroyed and its memory is reallocated.
That is correct. "reallocated" is not correct word I would use. I would phrase that as: The memory used by the object is available to be used by other objects.
And then you asked:
If I have a class and it's method creates a variable, shouldn't that variable be destroyed after the method call?
That is correct.
However, your situation is different.
When you use:
pairs.push_back(x);
a copy of x is placed in pairs. The copy continues to live in pairs after the function returns. Hence, printPairs() and removePair() work just fine.
First, access to variables out of scope is undefined behavior. The program might throw an error but it might even work well. So there's no guarantee an error will be raised.
Second, std::vector::push_back makes a copy of its arguments. So nothing to worry about when passing local variables to it.

At which line is the copy constructor called?

I have a few lines of code and I don't get, why and where the copy constructor is called. Could you explain it to me?
The output is:
CS10
CS99
CC100
Obj10=Obj100
D100
Obj10=Obj99
D99
D10
This is my source code:
#include <iostream>
using namespace std;
class my
{
int m;
public:
my(int i): m(i)
{
cout << "CS" << m << endl;
}
my(const my& c): m(c.m+1)
{
cout << "CC" << m << endl;
}
~my()
{
cout << "D" << m << endl;
}
my& operator=(const my &c)
{
cout << "Obj" << m << "=Obj" << c.m << endl;
return *this;
}
};
my f(my* x)
{
return *x;
}
int main()
{
my m1(10);
my m2(99);
m1 = f(&m2); // creates a new object
m1 = m2; // does not create a new object
}
Why and where is copy constructor called causing the output CC100 and D100?
In this function
my f(my* x)
{
return *x;
}
called in statement
m1 = f(&m2); // creates a new object
the copy constructor is called to copy object *x in the return temporary object.
In fact it looks as
my tmp = *x; // the copy constructor is called
m1 = tmp;
When trying to think about when a copy constructor is called you should keep a few things in mind:
Scope - functions can't see outside of themselves and their associated namespace. If you want to pass a variable to a function you need to save it in the global environment, repush a scoped copy and then operate on it.
When you use passing by reference you operate on the global copy but since in this case you are returning the value that is pointed to and not a pointer you have to push that return value onto the stack separately because it is stored at a different temporary register address that is popped off the stack after you assign it to a permanent location in main. That's where the destructor comes in.
You made a temporary return value to pass the value out of your function so it's got to be deleted because L1, L2, and L3 cache are all prime real estate.
I highly recommend doing a little bit of reading on assembly code operations or even try compiling simple programs into assembly and seeing how the low level languages work under the hood. Cheers!

returning C++ stack variable

In this example, why is it ok to return a stack variable? When t() returns, why is it not returning garbage, since the stack pointer has been incremented?
#include << string >>
#include << vector >>
#include << iostream >>
using namespace std;
class X{
public:
X() { cout << "constructor" << endl; }
~X() { cout << "destructor" << endl; }
};
vector <X> t()
{
cout << "t() start" << endl;
vector<X> my_x;
int i = 0;
printf("t: %x %x %x\n", t, &my_x, &i);
my\_x.push\_back(X()); my\_x.push\_back(X()); my\_x.push\_back(X());
cout << "t() done" << endl;
return my_x;
}
int main()
{
cout << "main start" << endl;
vector <X> g = t();
printf("main: %x\n", &g);
return 0;
}
output:
./a.out
main start
t() start
t: 8048984 bfeb66d0 bfeb667c
constructor
destructor
constructor
destructor
destructor
constructor
destructor
destructor
destructor
t() done
main: bfeb66d0
destructor
destructor
destructor
Basically when you return the stack variable my_x you would be calling the copy constructor to create a new copy of the variable. This is not true, in this case, thanks to the all mighty compiler.
The compiler uses a trick known as return by value optimization by making the variable my_x really being constructed in the place of memory assigned for g on the main method. This is why you see the same address bfeb66d0 being printed. This avoids memory allocation and copy construction.
Sometimes this is not at all possible due to the complexity of the code and then the compiler resets to the default behavior, creating a copy of the object.
Because parameters are passed by value. A copy is made. So what is being returned is not the value on the stack, but a copy of it.
Well a copy is returned, the only construct you can not return a copy of it is a static array. So you can not say this...
int[] retArray()
{
int arr[101];
return arr;
}
The compiler is optimized to handle returning "stack variables" without calling the copy constructor. The only thing you need to know about is that that memory allocation is in scope of both the function that allocated it on the stack and the function that the object is returned to.
It does NOT call the copy constructor nor does it allocate it twice.
There may be some special cases and of course it depends on the compiler -- for example, primitives may be copied -- but in general, objects allocated on the stack, don't get copied when being returned.
Example:
struct Test {
};
Test getTest() {
Test t;
std::cout << &t << std::endl; // 0xbfeea75f
return t;
}
int main(int argc, char *argv[])
{
Test t = getTest();
std::cout << &t << std::endl; // also 0xbfeea75f
}