#c
#c
Вопрос:
#include <iostream>
#include <vector>
using namespace std;
class base
{
int x;
public:
base(int k){x =k; }
void display()
{
cout<<x<<endl;
}
base(const baseamp;)
{
cout<<"base copy constructor:"<<endl;
}
};
int main()
{
vector<base> v;
base obase[5]={4,14,19,24,29};
for(int i=0; i<5; i )
{
v.push_back(obase[i]);
}
}
Когда данные вставляются в вектор, копирование этих данных отправляется в вектор с помощью конструктора копирования.
Когда я запускаю эту программу,
- для первой вставки (i=0) вызывается конструктор копирования один раз.
- для второй вставки (i = 1) вызывается конструктор копирования два раза
- для третьей вставки (i = 3) вызывается конструктор копирования три раза
- для четвертой вставки (i = 3) вызывается конструктор копирования четыре раза
- для пятой вставки (i = 4) вызывается конструктор копирования пять раз
Пожалуйста, кто-нибудь может сказать мне, почему это происходит? Для каждой вставки не следует вызывать конструктор копирования только один раз?
Ответ №1:
вызывает push_back()
увеличение размера вектора по мере необходимости, что включает копирование содержимого вектора. Поскольку вы уже знаете, что он будет содержать пять элементов, либо v.reserve(5);
непосредственно перед циклом, либо используйте конструктор range:
base obase[5]={4,14,19,24,29};
vector<base> v(obase, obase 5);
Комментарии:
1. Другим обходным путем является использование
std::deque<>
вместоstd::vector<>
, если не требуется компоновка непрерывной памяти.
Ответ №2:
Ваш конструктор копирования неисправен, вы забыли фактически скопировать данные 🙂
base(const baseamp; that) : x(that.x)
{
cout << "base copy constructorn";
}
Кроме того, если у вас современный компилятор, вы можете написать конструктор перемещения и узнать что-то новое:
base(baseamp;amp; that) : x(that.x)
{
cout << "base move constructorn";
}
Комментарии:
1. Вы абсолютно правы. Пожалуйста, не могли бы вы также объяснить, зачем «const» нужен в конструкторе копирования. если я не использую его, это выдает ошибку компиляции.
2. @Alok: Потому что ссылки на неконстантные значения не привязываются к rvalues. Если это звучит слишком технически для вас, не волнуйтесь. На практике все конструкторы копирования имеют const, потому что они только считывают из источника и не изменяют его. Не было бы смысла удалять const .
3. Большое спасибо, очень приятное описание
Ответ №3:
Если v
необходимо изменить размер его внутреннего буфера, он обычно выделяет совершенно новую область памяти, поэтому ему необходимо скопировать все объекты, которые ранее были в векторе, в новое местоположение. Это делается с помощью обычного копирования, поэтому вызывается конструктор копирования.
Вам следует вызвать reserve()
вектор, чтобы заранее зарезервировать хранилище, если вы можете оценить, сколько элементов вам понадобится.
Обратите внимание, что поведение изменения размера / увеличения std::vector
зависит от реализации, поэтому ваш пример кода будет выдавать разные результаты с разными реализациями стандартной библиотеки.
Комментарии:
1. Пожалуйста, не могли бы вы также объяснить, почему в конструкторе копирования мне нужен const ketyword? если я его не использую, это выдает ошибку компиляции?