Конструктор в C++

Конструктор в языке С++ служит для создания объекта (выделения под него памяти, инициализации значений) а деструктор служит для уничтожения объекта (освобождении выделенной памяти).

#include <iostream>                 // cout, endl
#include <iomanip>                  // setw, left
using namespace std;
class User{                         // Класс User
    string m_name;                  // Свойства класса имя
    int m_age;                      // Свойства класса возраст
public:
    User(string name, int age){     // Конструктор с параметрами name и age
        m_name = name;
        m_age = age;
        cout << "name = " << setw(10) << left << name << "age = " << age << endl;
    };
    
    User(string name, char age)     // Конструктор с прямой инициализацей (то же самое)
        :m_name(name), m_age(age){}
};
int main(){
    User Victor = User("Victor", 43); // Основная форма вызова конструктора
    User Anna("Anna", 42);            // Сокращенная форма
    User * Ray = new User("Ray", 36); // Указатель на динамический объект
    //В C++11 возможна списковая инициализация
    User Alex = {"Alex", 46};         // C++11
    User Dimon{"Dimon", 42};          // C++11
    User Dimon_copy {Dimon};          // Создание копии объекта Dimon
    User* Andrey = new User{"Andrey", 55}; // C++11 Ссылка на динамический объект
    User R37[3]{{"Victor", 43}, {"Semen", 42}, {"Stas", 42}}; // Создание массива объектов с параметрическим конструктором
    return 0;
}
/* Вывод программы
name = Victor    age = 43
name = Anna      age = 42
name = Ray       age = 36
name = Alex      age = 46
name = Dimon     age = 42
name = Andrey    age = 55
name = Victor    age = 43
name = Semen     age = 42
name = Stas      age = 42
*/ 

Конструктор копирования. Конструктор перемещения Перегрузка оператора присваивания =. Перегрузка оператора []

- При использовании в классе указателей, после копирования или присваивания объектов может оказаться что они ссылаются на одни и те же данные. Для решения этой и других проблем, используют явные конструкторы копирования и перемещения и перегрузку оператора присваивания или перемещения. Рассмотрим возможные варианты:

- Конструктор копирования вызывается при создании объекта и операторе = на другой объект того же класса. T obj = obj1;

- Конструктор копирования вызывается при создании объекта и передачи ему в качестве аргумента (в круглых скобках) другого объекта того же класса по lvalue ссылке. T obj(T& obj1);


- Конструктор перемещения вызывается при создании объекта и операторе = на другой rvalue объект того же класса. T obj = std::move(T&& obj1);

- Конструктор перемещения вызывается при создании объекта и передачи ему в качестве аргумента (в круглых скобках) другого объекта того же класса по rvalue ссылке. T obj(std::move(T&& obj1));


- Оператор присваивания вызывается при уже созданном объекте и операторе = на другой объект того же класса. Реализация оператора присваивания - это перегрузка оператора =, которому передается аргумент(объект) по lvalue ссылке, если передавать аргумент (объект) по значению, то будет произведено предварительное копирование объекта - вызов конструктора копирования. obj = obj1;

- Оператор перемещения вызывается при уже созданном объекте и операторе = на другой rvalue объект того же класса. Реализация оператора перемещения - это перегрузка оператора =, которому передается аргумент(объект) по rvalue ссылке. obj = std::move(obj1);

- В конструкторе присваивания используют возврат из функции объекта класса, для того чтобы можно было каскадировать присваивания a = b= c;


#include <iostream>

class My{
public:
    int id; // Идентификатор объекта
    My(int id_m = 0){   // Конструктор
        id = id_m;      // Выполняем какие-то действия
        std::cout << "Constructor id = " << id << "\n";  // Выводим сообщение
    }

    My(const My& obj){   // Конструктор копирования, принимает lvalue ссылку
        std::cout << "Copy constructor\n";          // Выводим сообщение
        id = obj.id; // Выполняем какие-то действия
    }

    My(const My&& obj){   // Конструктор перемещения принимает rvalue ссылку
        std::cout << "Move constructor\n";          // Выводим сообщение
        id = obj.id; // Выполняем какие-то действия
    }

    My& operator = (My& obj){   // Оператор присваивания принимает lvalue ссылку или объект
        std::cout << "Operator=\n"; // Выводим сообщение
        return obj; // Выполняем какие-то действия и возвращаем объект типа My
    }

    My& operator = (My&& obj){   // Оператор перемещения принимает rvalue ссылку
        std::cout << "Move operator=\n"; // Выводим сообщение
        return obj; // Выполняем какие-то действия и возвращаем объект типа My
    }
};

int main() {
    My s;       //Constructor id = 0    Конструктор
    My ss(3);   //Constructor id = 3    Конструктор

    My c = s;   //Copy constructor      Конструктор копирования
    My cc(s);   //Copy constructor      Конструктор копирования

    My m(std::move(s));     //Move constructor  Конструктор перемещения, т.к. std::move() приводит объект к rvalue
    My mm = std::move(ss);  //Move constructor  Конструктор перемещения,

    c = s;                  //Operator=         Оператор присваивания (объект c уже создан ранее)
    c = std:: move(s);      //Move operator=    Оператор перемещения

    ss = s = c;  // Каскадирование операторов присваивания (будет дважды вызван конструктор копирования)
}

#include <iostream> // cout
using namespace std;
class Vector{   // Класс Vector
    int size;   // Размер массива
    int *data;  // Указатель на данные массива
public:
    Vector(int s):size(s), data(new int[s]){cout << "Constructor \n";} // Конструктор
    Vector(const Vector& v){ // Конструктор копирования, без него v3[0] = 9
        cout << "Copy constructor \n";
        size = v.size;                  // Копируем размер массива
        data = new int[size];           // Создаем новый массив с размером как у источника
        for(int i = 0; i < size; i++){  // Заполняем идентичными данными
            data[i] = v.data[i];
        }
    }
    Vector& operator = (Vector& v){ // Оператор присваивания (перегрузка оператора =)
        cout << "Operator=";
        size = v.size;                  // Копируем размер массива
        data = new int[size];           // Создаем новый массив с размером как у источника
        for(int i = 0; i < size; i++){  // Заполняем идентичными данными
            data[i] = v.data[i];
        }
        return *this;                   // Возвращаем объект (не ссылку)
    }
    int& operator [](int index){ // Перегрузка оператора [] для обращения "как к массиву". int& className::operator [](int index){ должно быть в классе
        cout << " \nOperator [] ";
        return data[index];         // Возвращаем результат работы оператора (данные в массиве с индексом)
    }
    ~Vector(){ // Деструктор
        delete [] data; // Удаляем массив
    }
};

int main(){
    Vector v1(3);  //Constructor       Конструктор
    Vector v2(3);  //Constructor       Конструктор
    Vector v3(v1); //Copy constructor  Конструктор копирования.  v3 это независимая копия v1
    v2 = v3;       //Operator=         Оператор присваивания. v2 это независимая копия v1
    v1[0] = 9;     //Operator []       Не меняет v2 и v3
    v2[0] = 7;     //Operator []       Не меняет v1 и v3
    v3[0] = 5;     //Operator []       Не меняет v1 и v2
    cout << v1[0]; //Operator [] 9
    cout << v2[0]; //Operator [] 7
    cout << v3[0]; //Operator [] 5
}
/* Вывод в программы
Constructor 
Constructor 
Copy constructor 
Operator= 
Operator []  
Operator []  
Operator []  
Operator [] 9 
Operator [] 7 
Operator [] 5
*/
2023-10-23



Понравилась страница?
Добавить в закладки
Или поделиться!

Связанные темы

Конструктор в C++. Конструктор копирования и оператор присваивания.
delete C++ оператор освобождения памяти и спецификатор ограничения доступа
explicit С++ запрет неявных преобразования при вызове конструктора
friend C++ дружественная функция имеющая доступ к закрытым членам класса
mutable C++ изменение членов константного объекта
new C++ динамическое выделение памяти
private С++, С++ приватные члены класса, С++ закрыты члены класса
protected C++ указание защищенных членов класса
public С++, С++ открытые члены класса
struct С++ структура
this C++ указатель на текущий объект класса
virtual C++ виртуальные функции