【问题标题】:Why rvalue reference member would be const?为什么右值引用成员会是 const?
【发布时间】:2021-10-03 21:43:55
【问题描述】:

我正在尝试为结构编写移动构造函数,但我不明白为什么我无法调用结构成员的移动构造函数:

#include <memory>

struct C
{
    std::unique_ptr<int[]> mVector;
    size_t                 mSize;

    C() = default;

    C(C &&temp)
    : mVector(temp.mVector)
    , mSize(temp.mSize)
    {}    
};

当我编译这个时,我得到:

gcc -c TempTest.cpp
TempTest.cpp: In constructor 'C::C(C&&)':
TempTest.cpp:9:23: error: use of deleted function 'std::unique_ptr<_Tp [], _Dp>::unique_ptr(const std::unique_ptr<_Tp [], _Dp>&) [with _Tp = int; _Dp = std::default_delete<int []>]'
9 |     , mSize(temp.mSize)
  |                       ^
In file included from c:/msys64/mingw64/include/c++/10.3.0/memory:83,
             from TempTest.cpp:1:
c:/msys64/mingw64/include/c++/10.3.0/bits/unique_ptr.h:723:7: note: declared here
 723 |       unique_ptr(const unique_ptr&) = delete;
     |       ^~~~~~~~~~

因为在构造函数中temp 是一个右值引用,它是非常量的,所以temp.mVector 应该是非常量并且应该调用unique_ptr 移动构造函数,但是它调用了被删除的复制构造函数。知道错误在哪里吗?

【问题讨论】:

    标签: c++ rvalue-reference


    【解决方案1】:

    为什么右值引用成员会是 const?

    不要假设它是const。您应该假设unique_ptr(const unique_ptr&amp;) 只是可用构造函数中的最佳匹配

    因为在构造函数中temp 是一个右值引用

    惊喜!它不是右值参考。

    当调用构造函数时,变量temp绑定到一个右值。现在它是一个命名变量,它不再是一个“临时”。它已成为一个左值。

    由于您知道在调用构造函数时值右值,因此您可以安全地移动成员,将它们转换回右值。

    C(C &&temp)
    : mVector(std::move(temp.mVector))
    //        ^^^^^^^^^ We know that temp CAME FROM an r-value,
    //                  so it can safely be moved.
    , mSize(temp.mSize)
    {}   
    

    【讨论】:

      【解决方案2】:

      尝试运行以下代码,一切都变得清晰:

      struct Test
      {
          Test(){}
          Test(const Test& r)
          {
              std::cout << "i am using the copy constructor :) " << std::endl;
          }
          
          Test(Test&& r)
          {
              std::cout << "I require std::move to be selected as possible overload.." << std::endl;
          }
          
      };
      
      int main()
      {
          Test first;
          Test second(first);
          
          Test third(std::move(second));
          return 0;
      }
      

      std::move 通过将右值引用 (Test&&) 传递给构造函数来帮助选择正确的构造函数重载。 在您的情况下,即使您的向量不是 const,编译器也会选择复制构造函数,只是因为它被认为是最佳匹配(隐式转换为 const 引用优于隐式转换为 r 值引用,因为第二个,与第一个不同,可能会修改值)添加 std::move 您可以选择正确的构造函数并解决您的问题。

      #include <memory>
      
      struct C
      {
          std::unique_ptr<int[]> mVector;
          size_t                 mSize;
      
          C() = default;
      
          C(C &&temp)
          : mVector(std::move(temp.mVector))
          , mSize(temp.mSize)
          {}    
      };
      

      【讨论】:

        猜你喜欢
        • 2016-12-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-01-19
        • 2017-04-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多