std::map object destructor getting called? - c++

I have a global map object which contains an ID and a class object, but I don't understand why the destructor for the objects in the map are getting called.
#include <map>
#include <iostream>
#include <cassert>
#include <chrono>
#include <thread>
class TestMapObject{
private:
std::string m_sName;
public:
TestMapObject(const std::string& sName){
std::cout << "Constructor called" << std::endl;
m_sName = sName;
}
~TestMapObject(){
std::cout << "Destructor called" << std::endl;
}
const std::string& GetName(){
return m_sName;
}
};
namespace Test{
enum ETestMapKeyId{
k_ETestMapKeyNone = 0,
k_ETestMapKeyFirst,
k_ETestMapKeySecond,
};
std::map<ETestMapKeyId, TestMapObject> g_tMap;
TestMapObject* GetMapObjectById(ETestMapKeyId eID){
auto itFound = g_tMap.find(eID);
assert(itFound != g_tMap.end());
return &itFound->second;
}
}
int main(){
Test::g_tMap.insert(std::pair<Test::ETestMapKeyId,TestMapObject>(Test::k_ETestMapKeyFirst,TestMapObject("Alice")));
Test::g_tMap.insert(std::pair<Test::ETestMapKeyId,TestMapObject>(Test::k_ETestMapKeySecond,TestMapObject("Mocha")));
//destructor gets called here
std::cout << " are we destructed? " << std::endl;
TestMapObject* tmKeyFirst = Test::GetMapObjectById(Test::k_ETestMapKeyFirst);
TestMapObject* tmKeySecond = Test::GetMapObjectById(Test::k_ETestMapKeySecond);
for(;;){
std::this_thread::sleep_for (std::chrono::seconds(1));
std::cout << tmKeyFirst->GetName() << std::endl ;
std::cout << tmKeySecond->GetName() << std::endl ;
}
return 0;
}
I'm able to retrieve a pointer to the objects with GetMapObjectById and continuously able to print their name (Which might be undefined behavior considering their destructor was called). But I'm unsure why the destructor gets called before the application ends..
Output
Constructor called
Destructor called
Destructor called
Constructor called
Destructor called
Destructor called
are we destructed?
---continues loop print
Alice
Mocha

What you see is not the std::map getting destroyed, but the temporaries you are using to insert elements in the map. You can use emplace to avoid the construction (and destruction) of that temporaries:
Test::g_tMap.emplace(Test::k_ETestMapKeyFirst,"Alice");
Test::g_tMap.emplace(Test::k_ETestMapKeySecond,"Mocha");
Live Demo

Related

why 2 times destructor called in this code?

sorry but I cant understand why 2 times destructor called?
#include <iostream>
#include <thread>
class myClass
{
public:
int integer;
void operator()()
{
std::cout << "class: " << integer << "\t" << std::this_thread::get_id() << std::endl;
}
myClass(int h)
: integer{h}
{
}
~myClass()
{
std::cout << "MyClass by int: " << integer << " destroyed!" << std::endl;
}
};
bool myFunc(int x)
{
myClass tempClass(x);
std::thread one(tempClass);
one.join();
if (x <= 0)
return 0;
else
return myFunc(x - 1);
}
int main()
{
myFunc(10);
return 0;
}
note : I'm just trying in MultiThreads. (training)
and one more problem is that why before joining thread , my class has destroyed!
In the line
std::thread one(tempClass);
a copy of tempClass is created. Later on, both instances of myClass are destroyed.
You can pass tempClass by reference by using std::ref, but then you have to guarantee that tempClass remains valid (e.g. does not go out of scope, is brought in an invalid state by the main thread) throughout the life time of your thread (one).
You can also move tempClass into the other thread. You would still end up with two destructor calls and it would hardly make any difference in your case, but if myClass is difficult to copy, it can make a difference. In that case, you may want to read up on move semantics.

Boost shared_ptr on class object

Say I have the following code:
controller.hpp
#include "testing.hpp"
#include <boost/shared_ptr.hpp>
class controller
{
public:
controller(void);
void test_func (void);
boost::shared_ptr <testing> _testing;
}
controller.cpp
#include "controller.hpp"
controller::controller() {
boost::shared_ptr <testing> _testing (new testing);
std::cout << _testing->test_bool << std::endl;
}
void controller::test_func (void) {
// how to use _testing object?
std::cout << _testing->test_bool << std::endl;
return;
}
int main (void) {
controller _controller; // constructor called
test_func();
return 0;
}
testing.hpp
class testing
{
public:
bool test_bool = true;
}
Am I using a shared_ptr properly here for a class member? Multiple functions in class controller need to use the _testing object, and I don't want the testing classes' constructor / deconstructor to be called every time the pointer goes out of scope. Maybe this cant' be avoided, I'm starting to realize.
The testing object get constructed in controller constructor and destructed when it go out of the scope.
Just:
int main (void) {
controller _controller; // constructor called
_controller.test_func();
// destructor of controller called, because it go out of scope,
// so testing destructor is called too because, there is no more
// shared_ptr pointing to it!
}
[EDITED] To match question owner edits
I've taken the liberty of rewriting your code to demonstrate a usage of a shared pointer. Pretty typically it is used so an object can be in two places at once, moved around, and destruction is automatic.
#include <iostream>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
class testing
{
public:
std::string str;
testing( const char* in ) : str( in ) { }
};
typedef boost::shared_ptr <testing> SP_testing;
class controller
{
public:
controller( const char* in );
void test_func ( );
SP_testing _testing;
};
controller::controller( const char* in )
:_testing( boost::make_shared< testing >( in ) )
{
std::cout << "controller constructor: \"" << _testing->str << '\"' << std::endl;
}
void controller::test_func (void) {
std::cout << "test_func: \"" << _testing->str << "\" - cnt: " << _testing.use_count( ) << std::endl;
}
int main (void)
{
//yet to be used shared pointer
SP_testing outsider;
{
//this will create an instance of testing.
controller _controller( "this is a test" ); // constructor called, prints
outsider= _controller._testing; //assign shared pointer
_controller.test_func( ); // test called, prints usage count.
}//leaving scope, _controller will be destroyed but the _testing it created will not
std::cout << "outsider: \"" << outsider->str << "\" - cnt: " << outsider.use_count( ) << std::endl;
//now testing will get destroyed.
return 0;
}
Above, 'outsider' took a pointer to controller::_testing. At test_func they both have a pointer to the same object. Even though controller create the testing object it does not get destroyed when controller gets destroyed. Very handy when these kind of situations arise. This code can be pasted into one .cpp file. Thanks to #Dan MaĊĦek for the heads up on make_shared

static unique_ptr calls destructor twice

I use a singleton pattern which returns a reference to unique_ptr dereference. Here is the code,
#include <iostream>
#include <memory>
using std::cout; using std::endl;
using std::unique_ptr;
namespace Settings {
class Lazy {
Lazy() { cout << "Lazy::Lazy() " << this << endl; }
public:
~Lazy() { cout << "Lazy::~Lazy() " << this << endl; }
static Lazy &instance()
{
static unique_ptr<Lazy> lazy(new Lazy);
return *lazy;
}
};
Lazy &lazy()
{ return Lazy::instance(); }
}
int main()
{
cout << "main starts!" << endl;
auto state = Settings::lazy();
cout << "auto state = Settings::lazy() " << &state << endl;
cout << "main ends!" << endl;
return 0;
}
I was expecting that the destructor of the class would call only once but although the constructor called once destructor called twice, here is the output,
main starts!
Lazy::Lazy() 0xb1ec20
auto state = Settings::lazy() 0x7ffe17ae18b8
main ends!
Lazy::~Lazy() 0x7ffe17ae18b8
Lazy::~Lazy() 0xb1ec20
why destructor called twice? And even the second call this address is different.
Because you have 2 instances of the singleton, and both get destroyed.
The reason why you have to 2 singletons, is that when you get the singleton auto state = Settings::lazy(); a copy is created. You might be returning a reference, but state isn't a reference, so a copy is created.
Making state a reference fixes the problem: auto& state = Settings::lazy();
Rakete1111 solution is correct, but you might also want to delete the copy constructor and copy assignment for your singleton. That way you would prevent errors like this from ever happening.
Singleton class must disable any copy/move constructors & assignment/move operators.
Otherwise this is not a singleton.
Thus,
Lazy(Lazy &) = delete;
Lazy(Lazy &&) = delete;
Lazy &operator=(Lazy &) = delete;
Lazy &operator=(Lazy &&) = delete;
Then the following will be the only valid operation:
auto& state = Settings::lazy();

RAII Failure - Why Does this C++ Code Leak? - throw in ctor in try block prevents dtor

The output of the program below is:
begin try
Object() ctor
begin catch
Why is the Holder class's destructor not called? Is this a memory leak? Is it possible to call the Holder class's destructor without rethrowing?
#include <iostream>
#include <exception>
class Object
{
public:
Object() { std::cout << "Object() ctor" << std::endl; }
~Object() { std::cout << "~Object() dtor" << std::endl; }
};
class Holder
{
public:
Holder() :myObjectP( new Object() )
{
throw std::exception();
}
~Holder()
{
std::cout << "~Holder()" << std::endl;
delete myObjectP;
}
private:
Object* myObjectP;
};
int main(int argc, char* argv[])
{
try
{
std::cout << "begin try" << std::endl;
Holder h;
}
catch ( ... )
{
std::cout << "begin catch" << std::endl;
}
return 0;
}
In this case, your Holder object h is not fully constructued, that is that h's constructor had not finished its construction before the stack unwinding process had begun.
C++11 15.2 Constructors and destructors
(2)
An object of any storage duration whose initialization or destruction
is terminated by an exception will have destructors executed for all
of its fully constructed subobjects (excluding the variant members of
a union-like class), that is, for subobjects for which the principal
constructor (12.6.2) has completed execution and the destructor has
not yet begun execution.

Is STL Vector calling a destructor of a not-allocated object?

The folowing code shows an output not expected:
class test
{
public:
test()
{
std::cout << "Created" << (long)this << std::endl;
}
~test()
{
std::cout << "Destroyed" << (long)this << std::endl;
}
};
int main(int argc, char** argv)
{
std::vector<test> v;
test t;
v.push_back(t);
return EXIT_SUCCESS;
}
When executed it shows:
Created-1077942161
Destroyed-1077942161
Destroyed674242816
I think the second "Destroyed" output should not be there. When I don't use the vector the result is one Created and one Destroyed line as expected. Is this behavior normal?
(This is compiled with GCC on a FreeBSD system)
Everything is as it should be: there's the local variable t, which gets created and then destroyed at the end of main(), and there's v[0], which gets created and destroyed at the end of main().
You don't see the creation of v[0] because that happens by copy or move constructor, which your test class doesn't provide. (So the compiler provides one for you, but without output.)
For testing purposes it's handy to write for yourself once and for all a test class that contains all the possible constructors, destructors, assignment and swap operators and prints a diagnostic line in each, so you can witness how objects behave when used in containers and algorithms.
#include <cstdlib>
#include <vector>
#include <iostream>
class test
{
public:
test()
{
std::cout << "Created " << (long)this << std::endl;
}
test( const test& )
{
std::cout << "Copied " << (long)this << std::endl;
}
~test()
{
std::cout << "Destroyed " << (long)this << std::endl;
}
};
int main(int argc, char** argv)
{
std::vector<test> v;
test t;
v.push_back(t);
return EXIT_SUCCESS;
}
Output:
Created -1076546929
Copied 147865608
Destroyed -1076546929
Destroyed 147865608
std::vector::push_back copies the t object, you can see the copy constructor being invoked by the above code.
The vector is holding a copy of t, therefore after the call to push_back, you have two versions of t ... one on the stack, and one in the vector. Since the vector version was created by a copy-construtor, you don't see a "Created ..." prompt for that object ... but it still must be destroyed when the vector container goes out of scope, therefore you get two "Destroyed ..." messages.