Рубрики

Копировать конструктор в C ++

Мы обсудили введение в конструкторы в C ++ . В этом посте обсуждается конструктор копирования.

Что такое конструктор копирования?
Конструктор копирования — это функция-член, которая инициализирует объект, используя другой объект того же класса. Конструктор копирования имеет следующий общий прототип функции:

    ClassName (const ClassName &old_obj); 

Ниже приведен простой пример конструктора копирования.

#include<iostream>

using namespace std;

  

class Point

{

private:

    int x, y;

public:

    Point(int x1, int y1) { x = x1; y = y1; }

  

    // Копировать конструктор

    Point(const Point &p2) {x = p2.x; y = p2.y; }

  

    int getX()            {  return x; }

    int getY()            {  return y; }

};

  

int main()

{

    Point p1(10, 15); // Здесь вызывается нормальный конструктор

    Point p2 = p1; // Копируем конструктор здесь

  

    // Давайте получим доступ к значениям, назначенным конструкторами

    cout << "p1.x = " << p1.getX() << ", p1.y = " << p1.getY();

    cout << "\np2.x = " << p2.getX() << ", p2.y = " << p2.getY();

  

    return 0;

}

Выход:

p1.x = 10, p1.y = 15
p2.x = 10, p2.y = 15 

Когда вызывается конструктор копирования?
В C ++ конструктор копирования может вызываться в следующих случаях:
1. Когда объект класса возвращается по значению.
2. Когда объект класса передается (в функцию) по значению в качестве аргумента.
3. Когда объект строится на основе другого объекта того же класса.
4. Когда компилятор генерирует временный объект.

Однако не гарантируется, что конструктор копирования будет вызываться во всех этих случаях, поскольку стандарт C ++ позволяет компилятору оптимизировать удаление копии в определенных случаях, одним из примеров является оптимизация возвращаемого значения (иногда называемая RVO) .
Источник: http://espressocode.top/g-fact-13/

Когда нужен определяемый пользователем конструктор копирования?
Если мы не определяем наш собственный конструктор копирования, компилятор C ++ создает конструктор копирования по умолчанию для каждого класса, который выполняет поэлементное копирование между объектами. В общем, созданный компилятором конструктор копирования работает нормально. Нам нужно определять наш собственный конструктор копирования, только если у объекта есть указатели или какое-либо распределение ресурсов во время выполнения, например, дескриптор файла, сетевое соединение и т. Д.

Конструктор по умолчанию делает только поверхностное копирование.

Глубокое копирование возможно только с определенным пользователем конструктором копирования. В определяемом пользователем конструкторе копирования мы гарантируем, что указатели (или ссылки) копируемого объекта указывают на новые области памяти.

Конструктор копирования против Оператора присваивания
Какой из следующих двух операторов вызывает конструктор копирования, а какой — оператор присваивания?

MyClass t1, t2;

MyClass t3 = t1;  // ----> (1)

t2 = t1;          // -----> (2)

Конструктор копирования вызывается, когда новый объект создается из существующего объекта, как копия существующего объекта. Оператор присваивания вызывается, когда уже инициализированному объекту присваивается новое значение из другого существующего объекта. В приведенном выше примере (1) вызывает конструктор копирования и (2) вызывает оператор присваивания. Смотрите это для более подробной информации.

Написать пример класса, где нужен конструктор копирования?
Ниже приводится полная программа на C ++, демонстрирующая использование конструктора Copy. В следующем классе String мы должны написать конструктор копирования.

#include<iostream>
#include<cstring>

using namespace std;

  

class String

{

private:

    char *s;

    int size;

public:

    String(const char *str = NULL); // конструктор

    ~String() { delete [] s;  }// деструктор

    String(const String&); // копировать конструктор

    void print() { cout << s << endl; } // Функция для печати строки

    void change(const char *);  // Функция для изменения

};

  

String::String(const char *str)

{

    size = strlen(str);

    s = new char[size+1];

    strcpy(s, str);

}

  

void String::change(const char *str)

{

    delete [] s;

    size = strlen(str);

    s = new char[size+1];

    strcpy(s, str);

}

  

String::String(const String& old_str)

{

    size = old_str.size;

    s = new char[size+1];

    strcpy(s, old_str.s);

}

  

int main()

{

    String str1("GeeksQuiz");

    String str2 = str1;

  

    str1.print(); // что напечатано?

    str2.print();

  

    str2.change("GeeksforGeeks");

  

    str1.print(); // что печатается сейчас?

    str2.print();

    return 0;

}

Выход:

GeeksQuiz
GeeksQuiz
GeeksQuiz
GeeksforGeeks

В чем будет проблема, если мы удалим конструктор копирования из кода выше?
Если мы удалим конструктор копирования из вышеуказанной программы, мы не получим ожидаемый результат. Изменения, внесенные в str2, отражаются и в str1, чего никогда не ожидается.

#include<iostream>
#include<cstring>

using namespace std;

  

class String

{

private:

    char *s;

    int size;

public:

    String(const char *str = NULL); // конструктор

    ~String() { delete [] s;  }// деструктор

    void print() { cout << s << endl; }

    void change(const char *);  // Функция для изменения

};

  

String::String(const char *str)

{

    size = strlen(str);

    s = new char[size+1];

    strcpy(s, str);

}

  

void String::change(const char *str)

{

    delete [] s;

    size = strlen(str);

    s = new char[size+1];

    strcpy(s, str);

}

  

int main()

{

    String str1("GeeksQuiz");

    String str2 = str1;

  

    str1.print(); // что напечатано?

    str2.print();

  

    str2.change("GeeksforGeeks");

  

    str1.print(); // что печатается сейчас?

    str2.print();

    return 0;

}

Выход:

GeeksQuiz
GeeksQuiz
GeeksforGeeks
GeeksforGeeks

Можем ли мы сделать конструктор копирования закрытым?
Да, конструктор копирования может быть закрытым. Когда мы делаем конструктор копирования закрытым для класса, объекты этого класса становятся недоступными для копирования. Это особенно полезно, когда у нашего класса есть указатели или динамически распределяемые ресурсы. В таких ситуациях мы можем либо написать собственный конструктор копирования, как в примере выше String, либо создать личный конструктор копирования, чтобы пользователи получали ошибки компилятора, а не сюрпризы во время выполнения.

Почему аргумент в конструктор копирования должен быть передан как ссылка?
Конструктор копирования вызывается, когда объект передается по значению. Сам конструктор копирования является функцией. Поэтому, если мы передадим аргумент по значению в конструкторе копирования, будет сделан вызов конструктора копирования, чтобы вызвать конструктор копирования, который становится цепочкой вызовов без завершения. Поэтому компилятор не позволяет передавать параметры по значению.

Почему аргумент конструктора копирования должен быть константным?
Смотрите http://espressocode.top/copy-constructor-argument-const/

Эта статья предоставлена Shubham Agrawal . Если вам нравится GeeksforGeeks и вы хотели бы внести свой вклад, вы также можете отправить свою статью по адресу contrib@geeksforgeeks.org. Смотрите свою статью, появляющуюся на главной странице GeeksforGeeks, и помогите другим вундеркиндам.

Пожалуйста, пишите комментарии, если вы обнаружите что-то неправильное или вы хотите поделиться дополнительной информацией по обсуждаемой выше теме.

Рекомендуемые посты:

Копировать конструктор в C ++

0.00 (0%) 0 votes