我有一个相当大的Visual Studio C++代码库,很多人都在修改。需要删除可能许多其他对象引用的对象(使用原始指针的地址)。我试图尽可能多地删除地址引用,但恐怕还有一些我没有解决。
所以,我想知道是否有办法将所有对已删除地址的访问重定向到不同的地址,也许是在删除时做一些事情,这样它就不会崩溃?
该语言不支持您尝试使用原始指针执行的操作。如果你有选择使用std::shared_ptr
,你可以得到你想要的东西。
对OP评论的回应
使用delete
的目的是终止对象的寿命。
如果一个对象由多个客户端共享,则通过持有指向该对象的指针(彼此独立),您必须就如何管理对象的生命周期做出策略决策。
-
不要让对象的生存期结束,直到没有客户端有指向它的指针。这是
shared_ptr
实施的政策。 -
允许对象的生命期在第一个客户端想要结束时结束,同时确保其余客户端知道对象的生存期已结束。
您似乎要实施第二个策略。
直接在指针上调用delete
将无法实现该策略,因为该语言不支持该策略。
据我所知,标准库中没有支持该策略的智能指针类。但是,实现一个并不难。
下面是此类的演示性实现。
#include <iostream>
#include <cassert>
template <typename T>
struct my_shared_ptr
{
my_shared_ptr(T* ptr) : dataPtr_(new data(ptr))
{
}
my_shared_ptr(my_shared_ptr const& copy) : dataPtr_(copy.dataPtr_)
{
++(dataPtr_->use_count_);
}
~my_shared_ptr()
{
delete dataPtr_->ptr_;
--(dataPtr_->use_count_);
if ( dataPtr_->use_count_ == 0 )
{
delete dataPtr_;
}
else
{
dataPtr_->ptr_ = nullptr;
}
}
// Overloaded operator functions to use objects of
// the class as pointers.
T& operator*()
{
assert(dataPtr_->ptr_ != nullptr);
return *(dataPtr_->ptr_);
}
const T& operator*() const
{
assert(dataPtr_->ptr_ != nullptr);
return *(dataPtr_->ptr_);
}
T* operator->()
{
assert(dataPtr_->ptr_ != nullptr);
return dataPtr_->ptr_;
}
const T* operator->() const
{
assert(dataPtr_->ptr_ != nullptr);
return dataPtr_->ptr_;
}
struct data
{
data(T* ptr) : ptr_(ptr), use_count_(1) {}
T* ptr_;
size_t use_count_;
};
data* dataPtr_;
};
int main()
{
my_shared_ptr<int> ptr1{new int(10)};
std::cout << *ptr1 << std::endl;
my_shared_ptr<int> ptr2{ptr1};
std::cout << *ptr2 << std::endl;
{
my_shared_ptr<int> ptr3{ptr1};
std::cout << *ptr3 << std::endl;
}
// Problem. The int got deleted when ptr3's life ended
// in the above block.
std::cout << *ptr1 << std::endl;
return 1;
}
上述用g++
构建的程序的输出:
10
10
10
socc: socc.cc:35: T& my_shared_ptr<T>::operator*() [with T = int]: Assertion `dataPtr_->ptr_ != nullptr' failed.
Aborted
请注意,您至少需要实现复制赋值运算符,以使类确认三法则。您将需要进一步改进来处理指向基类和派生类的指针。