Constructor not throwing exception [duplicate] - c++

This question already has an answer here:
C++ constructor not called
(1 answer)
Closed 4 years ago.
In my code below, I wanted to test what would happen if I had an object, that contained another object whose constructor throws exception. But the code below does absolutely nothing. Nothing is printed on the console at all.
class A
{
public:
A()
{
cout << "in A constructor" << endl;
throw "error creating A";
}
~A()
{
cout << "destructing A" << endl;
}
};
class C
{
public:
C()
{
cout <<"in C constructor" << endl;
}
~C()
{
cout << "in C destructor " << endl;
}
};
class B
{
public:
C c;
A a;
B(A a_, C c_): a(a_), c(c_){}
B(){}
};
int main()
{
try{
B b(A, C);
//B b;
}
catch(char const* s)
{
cout <<"catching" << endl;
}
}
If in the try block, I use commented code instead, then it shows fine.
I also tried doing
B b(A(), C());
Still nothing.

This is a function declaration with return type B, name b, and two unnamed arguments of type A and C:
B b(A, C);
The same for
B b(A(), C());
as names can be enclosed by parentheses (to allow grouping, necessary when working with e.g. function pointers etc.), and even names that are left out can be enclosed by parentheses. You can turn it into a variable b of type B by
B b(A{}, C{});
One of the motivation for the curly braces to initialize variables was to disambiguate in such cases. Here, it obviously comes in handy.

Related

Deleting a pointer twice in C++ [duplicate]

This question already has answers here:
What is The Rule of Three?
(8 answers)
How to actually implement the rule of five?
(6 answers)
Closed 1 year ago.
I am new to code in C++. So, below code looks pretty decent to me.
#include<iostream>
using namespace std;
class B {};
class A {
public:
B* b;
A() {
cout << "ctor" << endl;
b = new B();
}
~A() {
cout << "dtor" << endl;
delete b;
}
};
void func(A a) {
cout << a.b << endl;
}
int main() {
A a;
cout << a.b << endl;
func(a);
cout << a.b << endl;
}
But I found an issue with this code. When I run this, it gives free(): double free detected in tcache 2 error. I know the cause of this error (it is because dtor is being called 2 times).
One way to solve the problem is, writing a copy constructor for class A where, I create a new B() like this.
A(A const& a) {
cout << "copy ctor" << endl;
b = new B();
*b = *a.b;
}
But if B is a very big class, and hence if I prefer to share b pointer, then how would I avoid this problem?

C++ - Destructor call order

I have the following C++ code:
#include <iostream>
struct A
{
A() { std::cout << "A" << ++x; }
A(int x) : A() { std::cout << x; }
~A() { std::cout << "D"; }
static int x;
};
int A::x = 0;
struct B
{
A a, aa, aaa;
B() : aa(1), a(2) { std::cout << "B" << std::endl; }
~B() { std::cout << "B" << A::x; }
};
B beta;
int main()
{
return 0;
}
I understand everything in the control flow except of destructor calls.
Here is the control flow without destructors:
create object B
call constructor B
call a,aa,aaa respectively
2.1 for a, call A(int x)
2.2 for aa, call A(int x)
2.3 for aaa, call A()
display B from B c-tor body
Now the 4. step is to call destructor B, I know that.
What I don't know is what is the order of calling destructors for A.
Is it a,aa,aaa respectively, or aaa,aa,a respectively?
Thanks in advance.
The member objects get destroyed in the reversed order they got constructed. Note that you do not influence this order by changing the order in the constructor's initialization list. The order is exclusively determined by the order you declare them in the struct/class definition.
What I don't know is what is the order of calling destructors for A. Is it a,aa,aaa respectively, or aaa,aa,a respectively?
Thus, the latter case is happening.
Everything looks fine. It constructs-destructs stack-wise (First in/Last out):
#include <iostream>
struct A
{
A() { name="untitled"; std::cout << name <<" constructor" << std::endl; }
A(std::string name):name(name) { std::cout << name <<" constructor" << std::endl; }
~A() { std::cout << name <<" destructor" << std::endl; }
std::string name;
};
struct B
{
A a, aa, aaa;
B() : aa("aa"), a("a") { std::cout << "B constructor" << std::endl; }
~B() { std::cout << "B destructor" << std::endl; }
};
B beta;
int main()
{
return 0;
}
Result:
a constructor
aa constructor
untitled constructor
B constructor
B destructor
untitled destructor
aa destructor
a destructor
Is this order guaranteed? yes
If you turn on all the warnings you see this:
g++ -Wall -Wreorder main.cpp
main.cpp: In constructor ‘B::B()’:
main.cpp:12:10: warning: ‘B::aa’ will be initialized after [-Wreorder]
A a, aa, aaa;
^
main.cpp:12:7: warning: ‘A B::a’ [-Wreorder]
A a, aa, aaa;
^
main.cpp:13:5: warning: when initialized here [-Wreorder]
B() : aa("aa"), a("a") { std::cout << "B constructor" << std::endl; }
^
This took forever to find, but per n4659 (ISO C++17 draft):
15.6.2 Initializing bases and members
paragraph (13.3)
Then, non-static data members are initialized in the order they were declared in the class definition (again regardless of the order of the mem-initializers).
[ Note: The declaration order is mandated to ensure that base and member subobjects are destroyed in the
reverse order of initialization. — end note ]
Here, mem-initializers are the list following the colon in the constructor definition.

Initializing derived classes through bases

Consider:
struct V {
V(int i) {
std::cout << "initialized v" << '\n';
}
};
struct A {
A() {
std::cout << "initialized a" << '\n';
}
};
struct B : virtual V, virtual A {
B(int i) :V{i} {
std::cout << "initialized b" << '\n';
}
};
class C : virtual V, virtual A {
public:
C(int i) : V{i} {
std::cout << "initialized c" << '\n';
}
};
class D : virtual public B, virtual public C {
public:
D(int i, int j) :V{i}, B{i}, C{j} {
std::cout << "initialized d" << '\n';
}
};
If I initialize D in main(), like this:
int main() {
D* d = new D{3,3}; //ok
B* b = new D{3,3}; //ok
C* c = new D{3,3}; //undefined
delete d;
delete b;
delete c;
}
But if I use a factory, like this:
C* factory() {
return new D{3,3};
}
int main() {
factory(); //ok
}
I can't figure out why it's causing undefined behavior when I initialize D through C in main() but works fine when I use other functions. What's wrong with C? Isn't it just the same as B?
Edit: So my code runs fine on this demo as I think it should. If there's nothing wrong with my code, is there a problem with my development environment? I'm using the latest mingw-w64 with eclipse CPP.
You are looking for the undefinedness in all the wrong places.
delete b;
delete c;
Both lines invoke undefined behavior, by deleting a derived class object (a D) through a pointer to base class (a B* or C*) with no virtual destructor. Give them one (e.g., by adding virtual ~V() = default; to V), and the crash should disappear.
This is why it's important to verify that the code you post here in fact reproduces the crash you are seeing when compiled and run. Someone would probably have spotted the problem in less than 5 minutes if the full code were available at the beginning. Instead, we spent 45 minutes trying to reproduce the problem.

Working of nested class objects?

I am trying to understand the order of exectution of a class which has nested objects of another class inside it. Here's my simple program :
#include<iostream>
#include <string>
using namespace std;
class Alpha
{
int a;
public:
Alpha(int x)
{
a=x;
}
};
class Beta
{ int b;
public:
Beta(int y)
{
b=y;
}
};
class Gamma
{
Alpha A;
Beta B;
int c;
public:
Gamma(int a,int b, int d): A(a), B(b)
{
c=d;
}
};
void main()
{
Gamma g(5,6,7);
}
As you can see, Gamma has 2 nested objects. Now when the first line of main() is executed, how does the execution start inside the class Gamma? The constructer is called first or the objects/data-members are created first?
The question of constructor execution order is simple: first, Gamma constructor starts, but then it immediately proceeds to initializing Alpha and Beta, as specified in your initialier list. Once the intializer list is done, the body of Gamma's constructor is executed.
There is an important twist to this: C++ will initialize nested objects in the order in which they are declared in the class, not in the order in which they are listed in the initializer list. In other words, Alpha will be initialized ahead of Beta even if you reverse A(a) and B(b):
// The compiler will issue a warning for this
Gamma(int a,int b, int d): B(b), A(a)
{
c=d;
}
The constructer is called first or the objects/data-members are created first?
From an initializer list the members or base class constructor calls are executed before the constructors body of the containing / inherited class.
You can easily check what's going on placing some output statements in the constructors
Alpha(int x) {
cout << "a = " << a << std::endl;
a=x;
cout << "Alpha(" << a << ")" << std::endl;
}
Beta(int y) {
cout << "b = " << b << std::endl;
b=y;
cout << "Beta(" << b << ")" << std::endl;
}
Gamma(int a,int b, int d): A(a), B(b) {
cout << "c = " << c << std::endl;
c=d;
cout << "Gamma(" << c << ")" << std::endl;
}
Output is
a = 0
Alpha(5)
b = 134514731
Beta(6)
c = -1218371596
Gamma(7)
See here for a fully working sample.
Objects in the initialization list are initialized first. Then, the body of the constructor inside {} is executed.

Constructor is not called in this aggregation class [duplicate]

This question already has an answer here:
Most vexing parse
(1 answer)
Closed 9 years ago.
class A {
public:
A() { cout << "A()" << endl; }
};
class B {
public:
A a;
B(const A& a1) : a(a1) { cout << "B(const A&)" << endl; }
/* B(const A& a1) { a = a1; cout << "B(const A&)" << endl; } */
};
int main() {
B b(A()); /* no ouput */
}
No output is generated for the above code. Is that due to the compiler optimization (copy elision) as discussed in this link?
But if I have a B class constructor and re-write the code like below:
class A {
public:
A() { cout << "A()" << endl; }
};
class B {
public:
A a;
B() {}
B(const A& a1) : a(a1) { cout << "B(const A&)" << endl; }
/* B(const A& a1) { a = a1; cout << "B(const A&)" << endl; } */
};
int main() {
B().a; // gives output A()
}
add an extra pair of parentheses:
B b((A()));
// you can also fix it using new C++11 initialization syntax:
B b{A()};
the problem you are facing it called most vexing parse, and it means compiler is not able to decide whether you want a function declaration or variable definition.
[edit]
I should also add that standard requires compiler in such case to choose function declaration.
[edit]
clang is actually more helpfull in this case, and gives hint to use partentheses:
http://rextester.com/PECQ53431
source_file.cpp:16:8: warning: parentheses were disambiguated as a function declaration [-Wvexing-parse]
B b(A()); /* no ouput */
^~~~~
source_file.cpp:16:9: note: add a pair of parentheses to declare a variable
B b(A()); /* no ouput */
^
( )
1 warning generated.
B b(A());
Is ambiguous and may be interpreted either as a variable declaration or as a declaration of a function that returns a restult of type B and takes a single unnamed parameter of type a function with no parameters and returns a result of type A. Although you may think first one should take place the standard dictates in fact the second one will happen. See the article about most vexing parse in wikipedia.
Instead of creating A object after B object creation, create first As object in main.
A a;
B b(a);