Копирует ли std :: vector range constructor [start, end) или просто ссылается на данные? - PullRequest
1 голос
/ 20 сентября 2019

Интересно, копирует ли конструктор диапазона std :: vector данные или просто ссылается на него?

Посмотрите на этот пример:

vector<int> getVector() {
    int arr[10];
    for(int i=0; i<10; ++i) arr[i] = i;
    return vector<int>(arr, arr+10);
}

Будет ли этовызвать ошибку (из-за раздачи ссылки на стек, который позже будет уничтожен) или это нормально, поскольку он копирует данные в конструкторе?

Edit # 1

Для пояснения:Я ищу более или менее официальный ресурс, который указывает, какие из следующих реализаций псевдокода конструктора являются допустимыми.Я знаю, что подпись конструктора отличается ... но вы должны понять.

Версия A (просто использует данные для внутреннего использования)

   template<typename T>
   class vector {
   private:
     T* data;
     int size;
   public:
     vector<T>(T* start, T* end) {
       data = start;
       size = (end - start);
     }
   };

Версия B (явно копирует данные)

   template<typename T>
   class vector {
   private:
     T* data;
     int size;
   public:
     vector<T>(T* start, T* end) {
       for(T* it = start; it < end; ++it) push_back(*it);
     }
   };

Ответы [ 4 ]

3 голосов
/ 20 сентября 2019

Стандартная библиотека C ++ указана несколько странным образом.

Указывается, что говорит о том, что требует каждый метод и что гарантирует каждый метод.Он не указан, как в «vector является контейнером значений, которым он владеет», даже если это базовая абстракция real здесь.

Формально то, что вы делаете, безопасно не потому, что«вектор копирует», но поскольку ни одна из предпосылок любого из методов вектора std не нарушается в копии вектора std, которую возвращает ваша функция.

Аналогично, значения устанавливаются как определенные, потому чтопостусловий конструктора, а затем предварительных и постусловий конструктора копирования и / или правил "elision" prvalue C ++ 17.

Но пытаться рассуждать о коде C ++ таким способом - безумие.

Семантически std :: vector - это регулярный тип со семантикой значения, которому принадлежат его собственные элементы.Обычные типы можно копировать, и копии ведут себя нормально, даже если исходный объект уничтожен.

Если вы не сделаете std::vector<std::reference_wrapper<int>>, вы в безопасности и небезопасны для справочной оболочки, потому что вы сохранили элементы, которые являютсяне обычные типы значений.

3 голосов
/ 20 сентября 2019

Как и все конструкторы std::vector<int>, здесь копируются целые числа.То же самое относится к таким методам, как push_back и insert

. Вот почему std::vector на самом деле имеет два аргумента шаблона.Второй по умолчанию равен std::allocator;это распределитель, используемый для выделения памяти для 10 целых чисел (и, возможно, еще нескольких, чтобы вектор мог расти - см. capacity)

[Edit] Фактический код больше всего похож на версию B, но, вероятно, похождо

template<typename T>
   class vector {
   private:
     T*     _Data = nullptr;
     size_t _Capacity = 0;
     size_t _Used = 0;
   public:
     vector<T>(T* start, T* end) {
       _Used = (end-begin);
       reserve(_Used); // Sets _Data, _Capacity
       std::uninitialized_copy(begin, end, _Data);
     }
   };
2 голосов
/ 20 сентября 2019

В случае сомнений проверьте ссылку .Ответ может быть получен из раздела Сложность, хотя я согласен, что нет явного подтверждения:

Сложность: делает только N обращений к конструктору копирования T (где Nэто расстояние между первым и последним) и без перераспределений, если первый и последний итераторы относятся к категориям прямого, двунаправленного или произвольного доступа.Он делает вызовы порядка N для конструктора копирования T и перераспределения logN порядка, если они являются просто входными итераторами.

0 голосов
/ 20 сентября 2019

Вектор не может быть определен как вектор ссылок, как, например, std::vector<int &>.Таким образом, код действителен.Вектор не содержит ссылок на элементы массива.Он создает новые элементы типа int (в качестве аргумента шаблона вектора), а не вектора ссылок.

...