当地址被取消引用时,是否可以重定向到不同的地址?

时间:2018-04-18 05:16:31

标签: c++ visual-studio pointers dangling-pointer

我有一个相当大的视觉工作室C ++代码库,许多人正在修改它。需要删除可能有许多其他对象引用的对象(使用原始指针的地址)。我试图尽可能地删除地址引用,但恐怕还有一些我没有解决的问题。

所以,我想知道是否有办法将删除地址的所有访问重定向到不同的地址,可能是在删除时执行某些操作以使其不会崩溃?

1 个答案:

答案 0 :(得分:1)

该语言不支持使用原始指针尝试执行的操作。如果您可以选择使用std::shared_ptr,则可以获得所需内容。

对OP评论的回应

使用delete的目的是终止对象的生命。

如果某个对象由多个客户端共享,则通过保持指向该对象的指针彼此独立,您必须就如何管理该对象的生命周期做出策略决策。

  1. 在没有客户端指向它之前,不要让对象的生命周期结束。这是由shared_ptr实施的政策。

  2. 当第一个客户端想要结束它时,允许对象的生命周期结束,同时确保其余客户端知道对象的生命周期已经结束。

  3. 您似乎想要实施第二项政策。

    直接在指针上调用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。您需要进一步改进以处理指向基类和派生类的指针。