我有一个相当大的 Visual Studio C++ 代码库,很多人都在修改它。需要删除可能有许多其他对象引用的对象(使用原始指针的地址)。我已尝试尽可能多地删除地址引用,但恐怕仍有一些我没有解决。
所以,我想知道是否有办法将所有对已删除地址的访问重定向到另一个地址,也许是在删除时做一些事情,这样它就不会崩溃?
我有一个相当大的 Visual Studio C++ 代码库,很多人都在修改它。需要删除可能有许多其他对象引用的对象(使用原始指针的地址)。我已尝试尽可能多地删除地址引用,但恐怕仍有一些我没有解决。
所以,我想知道是否有办法将所有对已删除地址的访问重定向到另一个地址,也许是在删除时做一些事情,这样它就不会崩溃?
该语言不支持您尝试使用原始指针执行的操作。如果您可以选择使用std::shared_ptr
,您可以得到您想要的。
使用的目的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
请注意,您至少需要实现复制赋值运算符以使课程符合三法则。您将需要进一步改进来处理指向基类和派生类的指针。