Итак, когда я обнаружил класс shared_ptr
(и его weak_ptr
брат), я полюбил его.Но потом один из наших парней сказал, что это слишком тяжело и дорого.Так что теперь у нас есть только сырые указатели и довольно тяжелый многопоточный конвейер.Из-за ошибок у нас есть ряд сбоев, которые нельзя защитить от нуля, потому что указатели на самом деле не являются нулевыми (но они являются мусором).Я думал о следующих конструкциях:
template<class T>
class GoodPtr {
public:
GoodPtr() {
std::lock_guard<std::mutex> lock(mux);
goodPtrs.emplace((T*)this);
}
virtual ~GoodPtr() {
std::lock_guard<std::mutex> lock(mux);
goodPtrs.erase((T*)this);
}
static bool isGoodPtr(T* ptr) {
// would love to use shared_mutex, but apparently it's not in c++11, so...
std::lock_guard<std::mutex> lock(mux);
return goodPtrs.find((T*)ptr) != goodPtrs.end();
}
private:
static std::unordered_set<T*> goodPtrs;
static std::mutex mux;
};
template<class T> std::unordered_set<T*> GoodPtr<T>::goodPtrs;
template<class T> std::mutex GoodPtr<T>::mux;
template <class T>
class GoodPtrHolder {
public:
GoodPtrHolder(){}
GoodPtrHolder(T* ptr) : _ptr(ptr) {}
void setPtr(T* ptr) {
_ptr = ptr;
}
T* operator->() {
if (_ptr && GoodPtr<T>::isGoodPtr(_ptr)) {
return _ptr;
} else {
static T dummy;
return &dummy;
}
}
private:
T* _ptr = nullptr;
};
Учитывая следующий пример:
class testo : public GoodPtr<testo> {
public:
testo() {}
virtual ~testo(){}
void doSomething() {
printf("sup %d\n", x);
}
void setX(int val) { x = val; }
private:
int x;
};
и:
auto *test = new testo;
GoodPtrHolder<testo> testHolder(test);
testHolder->setX(5);
testHolder->doSomething();
delete test;
testHolder->doSomething();
Это лучше или хуже, чем shared_ptr
, учитывая, что я должен вести статическую таблицу указателей?Есть ли лучший подход к проблеме?