#Confused about constructor with object parameter

63 messages · Page 1 of 1 (latest)

mystic hull
#

hi, I saw this question in homework:
A.h:

#include <iostream>
using namespace std;

class A
{
public:
    A(int a_value) 
    
     : a{a_value}
    { cout<<"A constructor\n"; }

    ~A()
    { cout<<"A destructor\n"; }

    int a;
};

B.h:

#include <iostream>
using namespace std;

class B
{
public:
    B(const A& A_obj_value, int b_value)

    : A_obj{A_obj_value}, b{b_value}
    
    { cout<<"B constructor\n"; }
    
     ~B()
    { cout<<"B destructor\n"; }

    A A_obj;
    int b;
};

main.cpp:

#include "A.h"
#include "B.h"

int main()
{
    A{1};
    B{A, 2};

    return 0;
}

Original question: "What is the output of the above program?"

The answer key says the output is supposed to be the following:

A constructor
B constructor
B destructor
A destructor
A destructor

so I don't just need the answer, my problem is that I don't understand why that is the answer. So I want to compile the program and add more print statements or step through it in debugger to try to understand what the program is doing, but unfortunately the program does not compile for me and I don't know how to make it compile. When I use g++ main.cpp I always see errors like this:

main.cpp: In function ‘int main()’:
main.cpp:7:11: error: no matching function for call to ‘B::B(<brace-enclosed initializer list>)’
    7 |     B{A, 2};
      |           ^

I tried changing some of the code to add object declarations or change curly braces to parentheses, but that did not help. Do you know what is needed for me to add in order to test this code?

unique tokenBOT
#

When your question is answered use !solved to mark the question as resolved.

Remember to ask specific questions, provide necessary details, and reduce your question to its simplest form. For more information use !howto ask.

random zenith
mystic hull
#

i didn't write the code it's from a homework question

random zenith
#

B-s constror takes in a const A& and an int, a only takes a int, not an const A&

#

wait holy im blind

#

mb mb I was making bad assumptions

mystic hull
#

what i suspect is that something might be "missing" like some lines of code or something that is needed to compile but isn't shown in the question,

random zenith
#

yeah this is how you could make it work

#

B take an A& but just writing A isn't valid as there isn't a default constructor

#

well not that
B{A,2} is valid it would need to be B{A{}, 2}

#

cause you need to pass in a valid A instance

mystic hull
#

but now, the output of the program is different from what the answer key said it should be and also this result i see isn't even in the list of multiple choice for the question

A constructor
A destructor
A constructor
B constructor
B destructor
A destructor
A destructor
#

does this mean the question is totally ill formed or a typo?

#

what i wonder now is, is there maybe a strange compiler that this code could happen to compile in that was tested to create the question , like "Turbo C++" or something?

oak ocean
#

Based on the original expected output, your almost definitely missing names for the variables in main

random zenith
#

well no :D

#

with this output the 2nd B is a anonomous object that gets constructed and dies very quickly

#

hence why the input is different

#

the way to get an exact ouput like the one above you need to do what sly described

oak ocean
#

The first A object is expected to outlive the B object, and it's highly likely the first A object should have been the argument to construct the B object

unique tokenBOT
#

@mystic hull Has your question been resolved? If so, run !solved :)

mystic hull
random zenith
#

you need to used named values

#

so objects get proper lifetime

oak ocean
#
int main()
{
    A a{1};
    B{a, 2};
#

The pain of typing on phone

#

You're not getting the remainder of main

#

But that's probably the minimal change

#

And if you copy pasted the original main above from your teacher then yeah he messed up

#

And if the exercise was to write the main then I overstepped and will see myself out

mystic hull
# oak ocean ```cpp int main() { A a{1}; B{a, 2}; ```

thank you but , changing my main.cpp to match what you just sent:

#include "A.h"
#include "B.h"

int main()
{
    A a{1};
    B{a, 2};

    return 0;
}

and recompiling, unfortunately it still has the output different from the "official" answer

A constructor
A destructor
A constructor
B constructor
B destructor
A destructor
A destructor
oak ocean
#

Yeah no, you messed up somewhere

#

You didn't save the file, most likely

random zenith
#

yea 🤔 this shouldn't create a temp somewhere

#

this looks like a mix?

oak ocean
#

Nah it's the exact same as before my suggestion

mystic hull
mystic hull
# oak ocean Yeah no, you messed up somewhere

im sorry you are right, i compiled but executed an old executable instead of the newly compiled one, when i run the correct executable it shows this

A constructor
B constructor
B destructor
A destructor
A destructor
#

thank you it looks like lines 6 and 7 in the original question's main.cpp were malformed then? if this is what is necessary for the code to actually compile

random zenith
#

overthinking stuff mb

mystic hull
#

now i would like to understand, why is ~A() called twice if there is only 1 object of A? and if there are actually 2 objects of A then why isn't A() also called twice?

#

that is what originally confused me about the answer to "what is the output"

random zenith
#

is there only 1 A objects ? ;)

mystic hull
#

hm

#

are there 2 objects of A and one of them is created by the custom normal constructor A() but the other one is created at line 7 by an invisible Default Copy Constructor for A class, which does not have a print statement?

#

is that right or is it inaccurate or more to it than that?

#

and then both of them have the defined destructor ~A() called on them automatically at the return which prints the 2x "A destructor"?

random zenith
#

bingo :)

#

pretty much sums it up

mystic hull
#

hold on in gdb it shows something different, it looks like the B and the second A are quickly constructed and destructed before the return is actually reached, leaving just one of the A in memory

#
Breakpoint 1, main () at main.cpp:5
5       {
(gdb) next
6           A a{1};
(gdb) n
A constructor
7           B{a, 2};
(gdb) n
B constructor
B destructor
A destructor
9           return 0;
(gdb) info locals
a = {a = 1}
#

maybe it is some type of optimization, i will compile with g++ -O0 -g main.cpp and see if it is any difference

#

not as far as i can tell - it looks like the first A object is not destroyed until 2 lines after the other objects

#
Breakpoint 1, main () at main.cpp:5
5       {
(gdb) n
6           A a{1};
(gdb) n
A constructor
7           B{a, 2};
(gdb) n
B constructor
B destructor
A destructor
9           return 0;
(gdb) n
10      }
(gdb) n
A destructor
random zenith
#

oh man this is hard to parse for me 🤔

#

but in the end the output is the same?

mystic hull
#

yes; oh well, thank you for helping i definitely understand it better now and i was really confused mostly by the original code not being valid C++ and I couldn't understand that the first A object was supposed to be passed to the constructor of B since it didn't have an identifier

#

!solved