Невозможно назначить nullptr в ссылке на пересылку после использования объекта для инициализации внутри конструктора перемещения - PullRequest
0 голосов
/ 26 августа 2018

Я пытаюсь привыкнуть к конструктору перемещения, и в одном из руководств было сказано, что всегда полезно инициализировать исходную ссылку на 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 в vector2D внутри конструктора перемещения, компилятор жалуется, говоря:

нет известного преобразования для аргумента 1 из std :: nullptr_t в std :: initializer_list из std :: vector.

Какие несколько правильных способов сделать такую ​​инициализацию.

Ответы [ 2 ]

0 голосов
/ 26 августа 2018

Здесь две вещи:

 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)) {}
0 голосов
/ 26 августа 2018

Вы должны написать, что:

// Not a move constructor, that would be `Matrix(Matrix&&)`
Matrix(std::vector<std::vector<T>>&& vector2D) : data(std::move(vector2D)) {
    std::cout<<"Move non-Constructor Called ...\n";
}

Векторы не могут быть nullptr, но они могут быть пустыми - data(std::move(vector2D)) очистит исходный вектор и переместит содержимое в data.

...