In following code example, there should be exist one instance of struct A
inside struct B
as long as any object of B
is living. Example works as expected.
#include <memory>
#include <iostream>
#include <mutex>
struct A
{
A() { std::cout << "A() called" << std::endl; }
~A() { std::cout << "~A() called" << std::endl; }
};
struct B
{
B()
{
std::cout << "B() called" << std::endl;
std::lock_guard<std::mutex> guard(mtx);
if( !refCount )
{
a.reset( new A );
}
++refCount;
}
~B()
{
std::cout << "~B() called" << std::endl;
std::lock_guard<std::mutex> guard(mtx);
--refCount;
if( !refCount )
{
a.reset( );
}
}
static std::unique_ptr<A> a;
static std::mutex mtx;
static int refCount;
};
std::unique_ptr<A> B::a;
int B::refCount(0);
std::mutex B::mtx;
int main()
{
{
B b1; //B::a should be created here
B b2;
} //B::a should be destroyed here
B b3; // B::a should be recreated here
} //B::a should be destroyed again here
See also http://coliru.stacked-crooked.com/a/fea428254933ee5c
My question: Is there an alternative (threadsafe!) implementation without a refcount? Is this maybe possible to solve with a construct of std::shared_ptr
and std::weak_ptr
?
The only way to ensure that an object lives "as long as any object of B
is living" is by keeping a refcount of B
objects. It's the only realistic way to tell if there are any living B
objects, if they are going to be arbitrarily created and destroyed as the program runs.
std::shared_ptr
internally keeps refcounts, which are tracked atomically. It's probably a better idea to use those, rather than manually managing the refcount yourself; that way you don't have to meticulously implement all of the RAII constructors, or reinvent the wheel.
Here is the solution wanted:
#include <memory>
#include <iostream>
#include <mutex>
using std::shared_ptr;
using std::weak_ptr;
struct A
{
A() { std::cout << "A() called" << std::endl; }
~A() { std::cout << "~A() called" << std::endl; }
};
struct B
{
B()
{ std::cout << "B() called" << std::endl;
std::lock_guard<std::mutex> guard(mtx);
if (!(ac =aw.lock()))
aw =ac =shared_ptr<A>(new A);
}
~B()
{ std::cout << "~B() called" << std::endl;
}
shared_ptr<A> ac;
static weak_ptr<A> aw;
static std::mutex mtx;
};
weak_ptr<A> B::aw;
std::mutex B::mtx;
int main()
{
{
B b1; //B::a should be created here
B b2;
} //B::a should be destroyed here
B b3; // B::a should be recreated here
} //B::a should be destroyed again here
which produces the same output as your example:
B() called
A() called
B() called
~B() called
~B() called
~A() called
B() called
A() called
~B() called
~A() called
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.