首页 > 解决方案 > 在使用对象初始化内部移动构造函数后,无法在转发引用中分配 nullptr

问题描述

我正在尝试习惯移动构造函数,并且在其中一个教程中被告知,在使用转发引用复制内容后初始化对 nullptr 的原始引用始终是一个好习惯。

#include <iostream>
#include <vector>
using namespace std;

template<typename T>
class Matrix{
  std::vector<std::vector<T>> data;
public :
  Matrix(const std::vector<std::vector<T>>& vector2D){ //Copy constructor for deep copy
    // Put some error handling to check the validity of vector2D

    std::cout<<"Copy Constructor Called ...\n";
    __uint32_t numRow = vector2D.size();
    __uint32_t numColumn = vector2D[0].size();

    data.resize(numRow,std::vector<T>(numColumn));

    for(auto row = 0u;row < numRow; ++row){
        for(auto column = 0u; column < numColumn; ++column){
            data[row][column] = vector2D[row][column];
        }
    }
  } 

  Matrix(std::vector<std::vector<T>>&& vector2D){   //Move constructor for shallow copy
    // Put some error handling to check the validity of vector2D
    std::cout<<"Move Constructor Called ...\n";
    data = vector2D;
    //vector2D = nullptr;    // we should assign the original reference to null in my knowledge
  }

  void displayVector(){
    __uint32_t numRow = data.size();
    __uint32_t numColumn = data[0].size();
    for(auto row = 0u;row < numRow; ++row){
        for(auto column = 0u; column < numColumn; ++column){
            std::cout<<data[row][column]<<"\t";
        }std::cout<<std::endl;
    }
  }

  Matrix operator+ (const Matrix& rhs){
    // Have to complete
    return data;
  }
  Matrix operator* (const Matrix& rhs){
    // Have to complete
    return data;
  }
};

int main() {
  cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!

  //Matrix<int> m1(std::vector<std::vector<int>>{{1,2},{3,4}});
  Matrix<int> m1({{1,2},{3,4}});
  m1.displayVector();

  std::vector<std::vector<int>> myVector{{5,6},{7,8}};
  Matrix<int> m2(myVector);
  m2.displayVector();
  return 0;
}

但是,当我试图将 nullptr 放入 move 构造函数中的 vector2D 时,编译器抱怨说

没有已知的参数 1 从 std::nullptr_t 到 std::vector 的 std::initializer_list 的转换。

有哪些可能正确的方法来进行这种初始化。

标签: c++c++11move

解决方案


这里有两件事:

 Matrix(std::vector<std::vector<T>>&& vector2D){   //Move constructor for shallow copy
// Put some error handling to check the validity of vector2D
std::cout<<"Move Constructor Called ...\n";
data = vector2D;
//vector2D = nullptr;    // we should assign the original reference to null in my knowledge

}

1)您应该移动接收到的向量,以调用向量移动赋值运算符:

data = std::move(vector2D);

2)无需手动将向量设置为nullptr,它的状态已经正确设置。您从中移动的向量处于“未知但有效的状态”,因此您可以使用它做任何不假设前提条件的事情(重新分配、检查大小、检查空虚等,但是您不能期望它会里面有有效值)。正如另一个答案提到的,您还应该直接初始化数据,而不是在构造函数体中进行,所以最终构造函数应该以这种方式实现:

 Matrix(std::vector<std::vector<T>>&& vector2D) : data(std::move(vector2D)) {}

推荐阅读