C++11 处理对自定义智能指针的悬空引用
免责声明:是的,我知道共享ptr。但我还是想这么做。 另外,我知道我没有使用锁或原子,因此这不是线程安全的 假设下面是一个“智能”指针的简单实现。语义是,如果通过值传递,则会增加引用计数;如果坚持引用,则会出现“弱”排序:C++11 处理对自定义智能指针的悬空引用,c++11,pointers,smart-pointers,C++11,Pointers,Smart Pointers,免责声明:是的,我知道共享ptr。但我还是想这么做。 另外,我知道我没有使用锁或原子,因此这不是线程安全的 假设下面是一个“智能”指针的简单实现。语义是,如果通过值传递,则会增加引用计数;如果坚持引用,则会出现“弱”排序: #pragma once #include <iostream> #include <cassert> using std::cout; template <class T> class Ptr { private: T* p
#pragma once
#include <iostream>
#include <cassert>
using std::cout;
template <class T>
class Ptr {
private:
T* ptr;
int* refCount;
public:
Ptr(T* ptr) {
assert(ptr);
this->ptr = ptr;
this->refCount = new int(1);
}
Ptr(Ptr& from) {
swap(*this, from);
}
Ptr(Ptr&& from) {
swap(*this, from, false);
}
Ptr& operator=(const Ptr& from) {
swap(*this, from);
return *this;
}
~Ptr() {
if (*refCount >= 1) {
(*refCount)--;
cout << "\n Ptr destructor: new ref count: " << *refCount;
if (*refCount == 0) {
delete ptr;
ptr = nullptr;
}
}
}
operator bool() {
return (*refCount >= 1);
}
T* operator->() {
assert(*refCount >= 1);
return ptr;
}
int referenceCount() {
return *refCount;
}
private:
template <class T>
void swap(Ptr<T>& to, Ptr<T>& from, bool isCopy = true) {
assert((*from.refCount) >= 1);
to.ptr = from.ptr;
to.refCount = from.refCount;
if (isCopy) {
(*to.refCount)++;
}
else {
from.ptr = nullptr;
}
}
};
class A {
public:
A() = default;
~A() {
cout << "\n dealloc:" << this;
}
void doSomething() {
}
};
void Test() {
{
Ptr<A> p1(new A);
cout << "\ncheckpoint - refCount (should be 1): " << p1.referenceCount();
Ptr<A> p2 = p1;
cout << "\ncheckpoint - refCount (should be 2): " << p1.referenceCount();
Ptr<A>& p3 = p1;
cout << "\ncheckpoint - refCount (should be 2): " << p1.referenceCount();
Ptr<A> p4 = std::move(p1);
cout << "\ncheckpoint - refCount (should be 2): " << p4.referenceCount();
Ptr<A> p5 = p4;
cout << "\ncheckpoint - refCount (should be 3): " << p5.referenceCount();
}
cout << "\nend";
}
但有一个大问题
假设我保留了这些引用中的任何一个(可能是这个问题的指针——任何充当弱引用的句柄),最后一个强引用超出了范围。原始指针现在为null,并且智能指针的计数器(我正在泄漏)仍然允许任何弱句柄正常工作,因为它仍然保持有效值0
但是,如果我删除了计数器指针,如果该内存位置被用于其他内容,那么剩下的任何引用最终都会指向其他数据,其中可能包括除0以外的任何数字
所以我想我可能需要包装一个指向0值的静态指针,而不是使用指向计数器指针的指针?这样,无论哪个强引用删除指针,都可以将所有计数器指向静态0
我有点困惑。特别是因为我正在查看渲染引擎的源代码,它们的共享ptr类与上面的代码非常相似。有一个原因是有两个计数器:一个用于数据,另一个用于数据。即使您不想使用std::shared_ptr(为什么?),您也可能会发现它很有用。我将查看实现说明,谢谢!但从你的评论来看,我开始认为应该保留两个计数器,即使强指针计数器变为0,也不应该删除refCounter,直到所有“观察者”真正消失,不管是弱还是强?关于我不想使用shared_ptr的原因:因为这是一个3d渲染器,我觉得shared_ptr就像stl中的很多东西都是臃肿的,如果它不需要适应所有可能的用例,性能可能会更高。有一个原因是有两个计数器:一个用于数据,一个用于数据。即使您不想使用std::shared_ptr(为什么?),您也可能会发现它很有用。我将查看实现说明,谢谢!但从你的评论来看,我开始认为应该保留两个计数器,即使强指针计数器变为0,也不应该删除refCounter,直到所有“观察者”真正消失,不管是弱还是强?关于我不想使用shared_ptr的原因:因为这是针对3d渲染器的,我觉得shared_ptr就像stl中的很多东西都很臃肿,如果它不需要适应所有可能的用例,那么性能可能会更好。
checkpoint - refCount (should be 1): 1
checkpoint - refCount (should be 2): 2
checkpoint - refCount (should be 2): 2
checkpoint - refCount (should be 2): 2
checkpoint - refCount (should be 3): 3
Ptr destructor: new ref count: 2
Ptr destructor: new ref count: 1
Ptr destructor: new ref count: 0
dealloc:00C3D060