2015-08-19 3 views
4

Предположим, у меня есть класс Matrix, с конструктором следующим образом:Как правильно определить конструктор копирования

Matrix::Matrix(int rows, int cols) 
{ 
    nrows = a; //here nrows is the number of rows for each matrix 
    ncols = b; //here ncols is the number of cols for each matrix 
    p = new double [rows*cols]; 
    for(int i=0;i<rows*cols;i++) 
     { 
      *p++ = 0.0; 
     } 
} 

Предположим, у меня тоже есть «копия» конструктор следующим образом:

Matrix::Matrix(const Matrix& mat) 
{ p = new double[mat.nrows*mat.ncols]; 
    for(int i=0;i<mat.nrows*mat.ncols;i++) 
     { 
      p[i] = mat.p[i]; 

     } 
} 

сейчас также предположим, у меня есть следующие строки в моей главной функции:

int main() 
    { 
     Matrix A(2,2); 
     Matrix B(2,2); 
     A = Matrix(B); //call overloaded assignment operator, and copy ctor/ 
    } 

Здесь оператор «=» перегружен присвоить все-ю e элементов в B до A. Моя проблема заключается в том, что после вызова конструктора копирования объект Matrix A является совершенно новым объектом.

Есть ли лучший способ написать конструктор копирования, чтобы, если матрица A уже существует, то вызов A = матрицы (B) приводит к ошибке?

+1

Почему вы этого не сделали? – NathanOliver

+1

Что вы подразумеваете под «Матрицей Объект - совершенно новый объект»? – Pradhan

+0

Вы не можете назначить объект, который еще не существует. Если вы хотите отклонить задание, спросите об этом. (Помните, что 'Matrix A = B;' не является назначением, а инициализацией.) – molbdnilo

ответ

8

Вместо того, чтобы использовать динамически выделенные массивы, я бы рекомендовал использовать std::vector

class Matrix 
{ 
public: 
    Matrix(long rows, long cols); 
private: 
    long nrows; 
    long ncols; 
    std::vector<double> p; 
} 

Тогда ваш конструктор может быть

Matrix::Matrix(long rows, long cols) 
: nrows(rows), 
    ncols(cols), 
    p(rows * cols) 
{ } 

Наряду с all of the other benefits использования std::vector над динамически выделенных массивов, теперь вы получите созданный компилятором, поэтому вам не нужно его писать.

Если вы не хотите, чтобы ваш класс был доступен для копирования, delete - конструктор копирования и оператор копирования.

class Matrix 
{ 
public: 
    Matrix(long rows, long cols); 
    Matrix(const Matrix& mat) = delete; 
    Matrix& operator=(const Matrix& mat) = delete; 
private: 
    long nrows; 
    long ncols; 
    std::vector<double> p; 
} 
0

Нет. Потому что тогда это не было бы копией конструктор. Конструкторы конструкторов.

2

Было бы далеко лучше удалить оператор присваивания:

Matrix& operator=(const Matrix&) = delete;

Тогда использование A = Matrix(B) будет испускать ошибку во время компиляции. Затем вам придется использовать конструктор, и ваша конкретная проблема перестанет быть актуальной.

+0

Спасибо за это ... не совсем уверен, но как работает '= delete'. Означает ли это, что любая специальная функция-член/оператор, определенный таким образом, не может быть вызвана? поэтому у нас нет оператора присваивания (включая оператор присваивания по умолчанию), и поэтому мы также используем конструктор копирования для присвоений? Еще раз спасибо! –

+0

Google «Удаление члена C++». – Bathsheba

3

С утверждением

A = Matrix(B); 

сначала временный объект является создание с помощью копирования-конструктор. Этот временный объект затем используется в присваивании.

Так что это правда, что используется копировальный конструктор, но не как часть назначения.

Смежные вопросы