从类型的右值开始无效初始化类型的非const引用

时间:2016-03-28 19:39:01

标签: c++ lvalue rvalue

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

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)
     ^

这两项改变都有效:

  1. 在运算符SmartPointer()的实现中,创建一个对象并返回:

    SmartPointer a(ptr _);

    返回a;

  2. 或者,将复制构造函数的参数设为const

    SmartPointer(const SmartPointer&amp; other)

    并评论该行

    other.ptr_ = nullptr;

  3. 为什么其中一种解决方案有效?感谢。

    #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;
    }
    

1 个答案:

答案 0 :(得分:2)

那是因为你的copy ctor有一个非const引用参数,因此无法接受临时参数。因此

return SmartPointer<X>(y);

不起作用。 return关键字的参数是临时的,需要复制,因此这里的设计会中断。

由于您使用的是C ++ 11,因此可以通过引入移动构造函数(并移动赋值)来解决此问题。

您还可以创建参数const并将ptr_成员指定为mutable。这将允许你从temporaries和const智能指针复制,但实际上是为了改变它们的价格。