unique_ptr 的 refcount 替代方案
Alternatives to refcount for unique_ptr
在下面的代码示例中,只要 B
的任何对象存在,就应该在结构 B
中存在一个结构 A
的实例。示例按预期工作。
#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
另见 http://coliru.stacked-crooked.com/a/fea428254933ee5c
我的问题:是否有没有引用计数的替代(线程安全!)实现?这也许可以用 std::shared_ptr
和 std::weak_ptr
的构造来解决吗?
确保对象存在 "as long as any object of B
is living" 的唯一方法是保持 B
个对象的引用计数。这是判断是否存在任何活动的 B
对象的唯一现实方法,如果它们将在程序运行时被任意创建和销毁。
std::shared_ptr
在内部保留引用计数,这些引用计数是自动跟踪的。使用它们可能是一个更好的主意,而不是自己手动管理引用计数;这样您就不必精心实现所有 RAII 构造函数,或重新发明轮子。
这是想要的解决方案:
#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
产生与您的示例相同的输出:
B() called
A() called
B() called
~B() called
~B() called
~A() called
B() called
A() called
~B() called
~A() called
在下面的代码示例中,只要 B
的任何对象存在,就应该在结构 B
中存在一个结构 A
的实例。示例按预期工作。
#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
另见 http://coliru.stacked-crooked.com/a/fea428254933ee5c
我的问题:是否有没有引用计数的替代(线程安全!)实现?这也许可以用 std::shared_ptr
和 std::weak_ptr
的构造来解决吗?
确保对象存在 "as long as any object of B
is living" 的唯一方法是保持 B
个对象的引用计数。这是判断是否存在任何活动的 B
对象的唯一现实方法,如果它们将在程序运行时被任意创建和销毁。
std::shared_ptr
在内部保留引用计数,这些引用计数是自动跟踪的。使用它们可能是一个更好的主意,而不是自己手动管理引用计数;这样您就不必精心实现所有 RAII 构造函数,或重新发明轮子。
这是想要的解决方案:
#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
产生与您的示例相同的输出:
B() called
A() called
B() called
~B() called
~B() called
~A() called
B() called
A() called
~B() called
~A() called