Вызывает ли vector.insert(…) конструктор или оператор присваивания?

#c #vector #constructor

#c #вектор #конструктор

Вопрос:

У меня есть вектор с элементами типа class A . Класс A имеет явно определенный конструктор копирования, но оператор копирования был сделан закрытым и неопределенным (он не предназначен для использования). Если я вставлю новые элементы в вектор, как показано ниже

 A walker;                      //This calls the default constructor.
std::vector< A > vec;
std::vector< A >::iterator it = vec.begin();
vec.insert( it, walker );      //Shouldn't this call the copy constructor?
 

Я получаю сообщение об ошибке, в котором сообщается, что оператор копирования является закрытым. Но разве vector не должен использовать конструктор копирования?

Комментарии:

1. Если вы реализуете либо, вы должны реализовать оба в любом случае ….

Ответ №1:

vector действительно ли используется конструктор копирования для вставленного элемента. Однако vector по-прежнему требуется оператор присваивания внутри, находится в пределах требований для vector типа, который можно назначить. Я считаю, что C 11 теперь требует только назначения перемещения.

Комментарии:

1. действительно. Это потребует либо перемещения, либо «классического» назначения.

2. @sehe Подождите, значит, C 11 обеспечивает самоанализ, необходимый для определения того, предоставляется ли тот или иной вариант? Это какой-то безбожный хакерский SFINAE или сейчас есть чистое решение?

3. @Karl Knechtel: Самоанализ не нужен, это делает перегрузка функций. Тем не менее, C 11 предоставляет SFINAE для выражений, которые должны позволять анализировать гораздо больше информации, чем то, что делает C 03.

4. @KarlKnechtel: требования к параметрам шаблона обычно явно не проверяются; иногда вы можете использовать некоторый шаблон библиотеки с типом, который не соответствует всем требованиям, не осознавая, что ваш код может иногда прерываться (например, если вы не используете функции-члены, для которых требуется это требование). Предполагалось, что это должно было быть улучшено в C 11 с помощью concepts , но от этого отказались. Однако даже в C 03 можно выполнить некоторый самоанализ во время компиляции, чтобы проверить наличие некоторых членов.

5. Это может быть связано со статическими утверждениями, чтобы убедиться, что данный тип соответствует необходимым требованиям. Несколько библиотек Boost предоставляют функции для достижения этой цели.

Ответ №2:

В msvc или gcc Vector.insert() внутренне вызывает функцию emplace() .

Во-первых, если емкость вектора равна размеру вектора, вектор перераспределяется с удвоенной емкостью.Сначала объект вставляется / перемещается (вызывается конструктор перемещения), а существующие объекты копируются в новое выделенное хранилище (вызывается конструктор копирования).

если емкость vector больше, чем size перед вызовом insertion, теперь, если nsertion не выполняется в конце, объект сначала вставляется / перемещается (вызывается конструктор перемещения), а существующий объект просто присваивается в том же хранилище (вызывается оператор присваивания copy is)

 #include <iostream>
#include<vector>
using namespace std;

class A
{
public:
    int i;
    A() = default;
    A(int k) :i(k) { cout << "init"; };
    A(const Aamp;amp;)
    {
        {cout << "move"; };
    }
    A(const Aamp;)
    {
        {cout << "copy"; };
    }
    Aamp; operator=(const Aamp;)
    {
        std::cout << endl << "assignment" << endl;
        return *this;
    }
   
};




int main()
{
    // vector<int> vi(5);  // just to show that std::vector always default initializes values amp; hence int will be 0 here

  // A a(2);
   // A a= 2;

    vector<A> va(4); // ---> calls default
    cout << "------" << va.capacity() << "-";
  

  va.emplace_back(2); 
 

  
    cout << "------"<<va.capacity()<<"-"<<va.size()<<"--";
    va.push_back(2);
    
    va.insert(va.begin(), 4);

    return 0;
}
 

——2-
инициализация перемещение копирование копирование
——4-3-

назначение initmove

назначение переместить назначение