class Foo{
public:
Foo(){
cout <<"C ";
}
~Foo(){
cout <<"D ";
}
};
void func(){
Foo* p = new Foo;
p = NULL;
}
int main(){
Foo a;
for (int i=0; i<1; i++){
Foo b;
if (true){
Foo c;
}
func();
}
return 0;
}
For this question, the output is C C C D C D D, and if I delete the func() in the main function, the output become C C C D D D, I understand the first 3 C where it come from, but I don't understand the remaining, please explain it, thanks.
The scope of the object a is the scope of the outer code block of the function main. It is the first object that is created and the last object that is deleted.
int main(){
Foo a;
// ...
return 0;
}
C C C D C D D
| |
a a
Then in the for loop that has only one iteration there is created the object b that is deleted after the first iteration of the loop
for (int i=0; i<1; i++){
Foo b;
// ...
}
C C C D C D D
| | | |
a b b a
Then in the block scope of the statement if
if (true){
Foo c;
}
there is created and deleted the object c
C C C D C D D
| | | | | |
a b c c b a
After that the function func is called
func();
Inside the function there is created an unnamed object using the operator new and pointed to by the pointer p.
void func(){
Foo* p = new Foo;
p = NULL;
}
C C C D C D D
| | | | | | |
a b c c p b a
This object is not deleted because the operator delete is not called for this object. So there is a memory leak.
That is all.
C - a is constructed
C - b is constructed
C - c is constructed
D - c is desctructed becouse you leave the scope
C - an object Foo is dynamically allocated and pointed to by p, but since it is dynamically allocated, and never deleted, it's never destructed.
D - b is destructed
D - a is destructed
There order would be for C C C D C D D:
C - Construct A
C - Construct B
C - Construct C
D - Destruct C
C - Construct p (in func)
D - Destruct B
D - Destruct A
// memleak for p (in func)
When the func(); call is included, the steps taken are:
Foo a; -> C
Foo b; -> C
Foo c; -> C
Left the scope of Foo c -> D
func(); call ->
new Foo; -> C
Finished func() call, left the scope of Foo b -> D
Left the scope of Foo a -> D
Note that the Foo object created in func() is never destructured, meaning you have a memory leak.
Related
I have a class:
class C {
public:
C(): _a(a++){}
private:
static int a;
int _a;
};
int C::a = 0;
C c = C(); // c._a is 0
C d = C(); // d._a is 1
C e = C(); // e._a is 2
This works out as I'd expect: a and obj._a increment by 1. But if I assign c, d, and e to an unordered_map, they increment by 2:
unordered_map<int, C> map;
C c = C(); // c._a is 0
map[0] = c;
C d = C(); // d._a is 2
map[1] = d;
C e = C(); // e._a is 4
map[2] = e;
How can I assign c, d, and e to map and still make the static int a increment by 1?
The problem comes from your map. When you access map[0], the map will look for the entry 0 and if it does not exists, will instantiate it and returns to you a reference to the new instance.
Try using map.emplace(0, c) instead to add an item in your map.
Your problem is that the expression map[0] is creating a default constructed 'C' (and incrementing the counter), and then that object is assigned to.
The solution is to directly insert the object in the map with:
map.insert({0,c});
Coming to C++ with a Java background, I'd like to set up some polymorphic code by initializing a variable of type A with one of two implementations, B or C.
My question is whether there is an easy way to do this on the stack. I have a case where I'm only using A inside the method body, and want it destroyed at the end of the function, so touching the heap is optional.
Here's how I would do it on the heap:
A* a = NULL;
if (p) {
B* b = new B();
b->setSomethingImplementationSpecific();
a = b;
}
else {
a = new C();
}
doSomething(a);
delete(a);
In practice I'd probably pull this out into a factory method, and use an auto_ptr to avoid the delete(a).
This works, but can I do it on the stack? My thought pattern is something like this:
A* a = NULL;
if (p) {
B b;
b.setSomethingImplementationSpecific();
a = &b;
}
else {
C c;
a = &c;
}
doSomething(a);
Now I don't have to bother with delete(a), but doSomething(a) won't work, since the B or C is destroyed when they go out of scope.
I've been trying to figure out a way to do part of it with the ternary operator as well, but I end up both borking up the syntax and taking the address of a temporary -- so am I right that there is no way to do this?
A * const a = &(p ? B() : C());
Advice on whether it's a silly idea to implement polymorphism on the stack in the first place is welcome, but mostly I'm trying to better understand the limits of C/C++ in this area, independently of design sense.
If you are using C++11, you can get "stack semantics" by using a unique_ptr:
std::unique_ptr<A> a = (p ? new B() : new C());
Although the object itself will still be allocated on the heap.
std::auto_ptr<A> is the equivalent idiom in C++03.
You can do this cleanly using std::aligned_union for storage:
template <typename...T>
using storage_t = typename std::aligned_union<0, T...>::type;
and a custom unique_ptr deleter:
struct placement_deleter {
template <typename T>
void operator () (T* ptr) const {
ptr->~T();
}
};
template <typename T>
using stack_ptr = std::unique_ptr<T, placement_deleter>;
Resulting in the usage:
storage_t<B, C> storage;
stack_ptr<A> a;
if (p) {
auto b = new (&storage) B();
a.reset(b);
b->setSomethingImplementationSpecific();
} else {
a.reset(new (&storage) C());
}
doSomething(*a);
See it live at Coliru.
Instead of this original code,
A* a = NULL;
if (p) {
B* b = new B();
b->setSomethingImplementationSpecific();
a = b;
}
else {
a = new C();
}
doSomething(a);
delete(a);
you can do this:
void doSomething( A const& ) {}
void doBeeDoo( B&& b )
{
b.doSomethingImeplementationSpecific();
doSomething( b );
}
void foo()
{
if( p ) { doBeeDoo( B() ); } else { doSomething( C() ); }
}
You could do something like this with boost::optional:
#include <boost/optional.hpp>
void example(bool p) {
boost::optional<B> b;
boost::optional<C> c;
A* a = nullptr;
if (p) {
b = B();
b->setSomethingImplementationSpecific();
a = b.get_ptr();
}
else {
c = C();
a = c.get_ptr();
}
doSomething(a);
}
Note that b and c must have a long-enough lifetime. But only one of them calls a constructor and destructor for B or C.
What you have won't work. b and c will be deleted from the stack by the time you get to doSomething(a);. However, you could do this:
if (p) {
B b;
b.setSomethingImplementationSpecific();
doSomething(&b);
}
else {
C c;
doSomething(&c);
}
I saw an online C++ test regarding the constructor. I can figure out most of the answers but am puzzled by some in the following. Hope someone can help me out.
Here's the example.
#include <iostream>
class A {
public:
A(int n = 0) : m_n(n) {
std::cout << 'd';
}
A(const A& a) : m_n(a.m_n) {
std::cout << 'c';
}
private:
int m_n;
};
void f(const A &a1, const A &a2 = A())
{
}
int main() {
A a(2), b;
const A c(a), &d = c, e = b;
b = d;
A *p = new A(c), *q = &a;
static_cast<void>(q);
delete p;
f(3);
std::cout << std::endl;
return 0;
}
What I don't really get is why "&d = c" doesn't output anything. Also adding another overloading constructor like A(const A *a) : m_n(a->m_n) { std::cout << 'b'; } doesn't output anything either for *q = &a. So what can I do to make it work?
Many thanks for any advice. I am very curious about this.
There's no output for these because d and q are not of type A, i.e. they are not A objects. d is a reference to A and q is a pointer to A. Initialising a reference and initialising or assigning a pointer does not manipulate the referred-to/pointed-to A object at all, hence no output.
To address your question - there is nothing to "make work," it works just as it should.
That to be more clear I will rewrite this statement
const A c(a), &d = c, e = b;
as
const A c(a);
const A &d = c;
Here d is declared as a reference to an object of type A. It does not create a new object. It refers to an object that is already created. In this case d referes to c. In fact d is simply an alias for object c.
This code snippet
A *p = new A(c), *q = &a;
also can be rewritten for simplicity
A *q = &a;
In this statement pointer q is simply assigned by the address of a. Neither object is created. Simply q now points to already created early object a.
&d = c doesn't output anything because you're not calling the constructor.
If we expand that code fragment a bit...
A &d = c
What your code is saying there is "declare d to be a reference to an object of type A, which points to c". Because you're creating a reference, you're not calling the constructor, c and d are the same object.
The same applies to q, but instead of creating a reference, you're creating a pointer and assigning it the address of an existing instance of type A. The constructor isn't called because you're not creating a separate object, you're linking to an existing one.
I have to write definition of the code below. I undarstand some basics of OOP Cpp, I know what is *x or &x, but that's not enough... The main fact is that i cant understand line B* p = new D, m, *k; i cant understand what m and *k stand for.
class B {
public:
virtual void msg() { cout << "classB"; }
};
class D: public B {
public:
virtual void msg() { cout << "classD"; }
};
int main() {
B* p = new D, m, *k;
p->msg(); k = &m; k->msg();
. . .
}
Help, if you can explain how (and why so) this code will work.
thanks, for your time.
It declares multiple variables at once. This is basically the same as:
B *p = new D;
B m;
B *k;
So p is a pointer to an instance of D allocated with new. m is a local instance of class B and k is a pointer to B that is later assigned to point at m.
The msg function is called on both allocated objects via the pointers p and k.
Note that * applies to each variable declaration separately. So B* a, b; doesn't declare two pointers, but instead declares one pointer and one local object. This is the reason, that many people prefer to write the * directly in front of the variable name: B *a, b makes this a bit more obvious.
In C++ you can declare more then one variable in one statement. Therefore B* p = new D, m, *k; declares the variables p, m and k. The * for pointer declarations binds to the variable name, therefore it's basically identical to
B* p = new D;
B m;
B* k;
Nothing fancy, it's just plain old C.
B* p = new D, m, *k;
is just shortcut for:
B* p = new D;
B m;
B* k;
p is a pointer to an object of the class B (or D, because it is a child of the class B). p->msg(); is similar to (*p).msg();. m is an object of the class B, so we can get pointer to it by & operator and store it in k (which is a pointer to an object of the class B).
And
B* p = new D, m, *k;
is just
B* p = new D;
B m;
B* k;
Notice: you should put * if it is needed each time
Having the following code:
#include <iostream>
struct A
{
int x;
A(){}
~A(){std::cout <<"~A("<<x<<")\n";}
};
struct B: public A
{
};
void f(A a)
{
a.x = 2;
}
void main()
{
B b;
std::cout <<"----------\n";
b.x = 1;
f(b);
b.x = 3;
std::cout <<"----------\n";
}
In this case the output is following:
----------
~A(2)
~A(1)
----------
~A(3)
The same code but virtual function is added to parent class:
#include <iostream>
struct A
{
int x;
A(){}
~A(){std::cout <<"~A("<<x<<")\n";}
virtual void ff() {}
A(A& ca): x(ca.x){}
};
struct B: public A
{
};
void f(A a)
{
a.x = 2;
}
void main()
{
B b;
std::cout <<"----------\n";
b.x = 1;
f(b);
b.x = 3;
std::cout <<"----------\n";
}
In this case we have the following output:
----------
~A(2)
----------
~A(3)
EDIT:
Compiler is: MSVCPP 10
The questions are the following:
Why we have double copying in the first case?
Why we have only one copying in the second case?
The 1st case: why does compiler not optimizes the 1st case (by reducing copy operations quantity)?
Does the following code:
void f(int);
//...
double d;
f(d);
also make double-copying?
The output on gcc 4.3.4 for both cases is:
----------
~A(2)
----------
~B
~A(3)
Example 1
Example 2
This output can be explained as:
When you call f(b); an copy of the object of type B is created since it is pass by value.
But there is Object slicing, since the function parameter takes on object of type A. Thus the object in the function now is of the type A and it gets destroyed while returning from the function resulting in call output ~A(2).
The following two traces are from the destruction of the object b which is created in the main(), Since it is of the type of B destructors for base class A and derived class B both are called for it.
I am not sure if I missed out any obvious optimization that gcc might be performing in this case but for me the outputs look pretty much as expected.