我正在根据一些更有效的c++的问题28智能指针编写一些代码,如下所示。但是,它不能编译:

main.cpp: In instantiation of 'SmartPointer<T>::operator SmartPointer<U>() [with U = MusicProduct; T = Cassette]':
main.cpp:99:17:   required from here
main.cpp:48:39: error: invalid initialization of non-const reference of type 'SmartPointer<MusicProduct>&' from an rvalue of type 'SmartPointer<MusicProduct>'
       return SmartPointer<U> (ptr_);
                                   ^
main.cpp:16:9: note:   initializing argument 1 of 'SmartPointer<T>::SmartPointer(SmartPointer<T>&) [with T = MusicProduct]'
     SmartPointer(SmartPointer<T>& other)
     ^

这两种更改均有效:
  • 在执行操作符SmartPointer()时,创建一个对象并返回:

    SmartPointer a(ptr_);

    返回
  • 或者,将复制构造函数的参数设置为const

    SmartPointer(const SmartPointer等)

    并评论这一行

    other.ptr_ = nullptr;

  • 两种解决方案都有效的原因是什么?谢谢。
    #include <iostream>
    
    template <typename T>
    class SmartPointer
    {
      public:
        SmartPointer(T* ptr) : ptr_(ptr) {}
        ~SmartPointer()
        {
          if (ptr_)
          {
            delete ptr_;
          }
        }
    
        SmartPointer(SmartPointer<T>& other)
        {
          ptr_ = other.ptr_;
          other.ptr_ = nullptr;
        }
    
        SmartPointer<T>& operator = (SmartPointer<T>& other)
        {
          if (this == &other)
          {
            return *this;
          }
    
          if (ptr_)
          {
            delete ptr_;
          }
    
          ptr_ = other.ptr_;
          other.ptr_ = nullptr;
    
          return *this;
        }
    
        template <typename U>
        operator SmartPointer<U> ()
        {
          // it works
          //SmartPointer<U> a(ptr_);
          //return a;
    
          // error
          return SmartPointer<U> (ptr_);
        }
    
        T& operator * () const
        {
          return *ptr_;
        }
    
        T* operator -> () const
        {
          return ptr_;
        }
    
      private:
        T* ptr_ = nullptr;
    };
    
    class MusicProduct
    {
    public:
      MusicProduct(const std::string& name) : name_(name) {}
      virtual ~MusicProduct() {}
    
      virtual void Play() const = 0;
      virtual void ShowName() const
      {
        std::cout << name_ << std::endl;
      }
    
    private:
      std::string name_;
    };
    class Cassette : public MusicProduct
    {
      public:
      Cassette(const std::string& name) : MusicProduct(name) {}
      void Play () const
      {
        std::cout << "play cassette" << std::endl;
      }
    };
    
    void CallPlay(const SmartPointer<MusicProduct>& sp)
    {
      sp->Play();
    }
    
    int main()
    {
      SmartPointer<Cassette> a(new Cassette("Zhang"));
      a->ShowName();
      CallPlay(a);
      return 0;
    }
    

    最佳答案

    这是因为您的复制ctor具有非常量引用参数,因此不能接受临时变量。从而

    return SmartPointer<X>(y);
    

    将无法正常工作。 return关键字的参数是一个临时变量,需要将其复制,因此此处的设计将失效。

    由于您使用的是C++ 11,因此可以通过引入move构造函数(和move分配)来解决此问题。

    您还可以设置参数const并将ptr_成员指定为mutable。这将允许您从临时变量和const智能指针中进行复制,但要付出代价,实际上要对其进行变异。

    07-25 20:30