Я немного не уверен, когда нужен конструктор копирования. Например, с учетом этой функции:
template<class T>
T max(const T* array, int size) {
T result = array[0];
for (int i = 1; i < size; ++i) {
if (result < array[i]) {
result = array[i];
}
}
return result;
}
По какой причине мне нужен конструктор копирования для типа T
? Я думаю, это должно быть потому, что мы возвращаемся по стоимости. Нужен ли для этой строки T result = array[0];
также конструктор копирования?
2 ответа
По какой причине мне нужно
copy constructor
для типаT
?
T result = array[0];
Это называется инициализацией копирования и вызывает конструктор копирования для типа T
. Для успешного выполнения этой строки типу T
потребуется конструктор копирования.
Я думаю, это должно быть потому, что мы возвращаемся по значению, и поэтому нам нужно
copy constructor
для типаT
.
return result;
По большей части ваше предположение верно для возвращаемого значения. Однако в этом случае определять конструктор копирования не обязательно. Чтобы реализовать семантику перемещения, вы можете реализовать конструктор перемещения, который устранит необходимость в конструкторе копирования , поскольку локальная переменная result
будет "перемещена" вместо "скопирована" из. Семантика перемещения устраняет необходимость в ненужных копиях больших объектов при их возврате из функции, поскольку эти большие объекты не будут доступны после возврата из функции.
На это уже ответили здесь:
В чем разница между оператором присваивания и конструктором копирования?
Итак, дело в следующем:
Конструктор копирования используется для инициализации ранее неинициализированного объекта из данных какого-либо другого объекта.
Оператор присваивания используется для замены данных ранее инициализированного объекта данными какого-либо другого объекта.
Вот пример:
#include <iostream>
using namespace std;
class MyClass{
public:
MyClass(){
cout << "Default ctor\n";
}
MyClass(const MyClass& copyArg){
cout << "Copy ctor\n";
}
MyClass(MyClass&& moveArg){
cout << "Move ctor\n";
}
void operator=(const MyClass& assignArg){
cout << "Assignment operator\n";
}
bool operator<(const MyClass& comparsionArg) const {
return true;
}
};
template<class T>
T max(const T* array, int size) {
T result = array[0];
for (int i = 0; i < size; ++i) {
if (result < array[i]) {
result = array[i];
}
}
return result;
}
int main(){
MyClass arr[1];
const MyClass& a = max(arr, 1);
return 0;
}
Чтобы узнать, что именно происходит, нам нужно скомпилировать с помощью -fno-elide-constructors
.
Результат:
Default ctor
Copy ctor
Assignment operator
Move ctor
Итак, здесь конструктор по умолчанию вызывается в этой строке для одного элемента массива:
MyClass arr[1];
Затем мы инициализируем ранее неинициализированный объект и вызывается конструктор копирования :
T result = array[0];
Затем мы присваиваем ранее инициализированному объекту и вызываем оператор присваивания :
result = array[i];
После того, как нам нужно создать объект за пределами области действия нашей функции, поскольку мы возвращаемся по значению и для этого конструктора перемещения вызывается:
return result;
Затем привяжите объект, созданный с помощью конструктора перемещения в области main
, к ссылке const:
const MyClass& a = max(arr, 1);
Похожие вопросы
Связанные вопросы
Новые вопросы
c++
C ++ - это язык программирования общего назначения. Первоначально он был разработан как расширение C и имеет аналогичный синтаксис, но теперь это совершенно другой язык. Используйте этот тег для вопросов о коде (который должен быть) скомпилирован с помощью компилятора C ++. Используйте тег для конкретной версии для вопросов, связанных с конкретной версией стандарта [C ++ 11], [C ++ 14], [C ++ 17], [C ++ 20] или [C ++ 23] и т. Д. .