我有一个相当大的视觉工作室C ++代码库,许多人正在修改它。需要删除可能有许多其他对象引用的对象(使用原始指针的地址)。我试图尽可能地删除地址引用,但恐怕还有一些我没有解决的问题。
所以,我想知道是否有办法将删除地址的所有访问重定向到不同的地址,可能是在删除时执行某些操作以使其不会崩溃?
答案 0 :(得分:1)
该语言不支持使用原始指针尝试执行的操作。如果您可以选择使用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
请注意,您需要至少实施复制赋值运算符才能使班级确认为The Rule of Three。您需要进一步改进以处理指向基类和派生类的指针。