Объясните, пожалуйста, что происходит

У меня есть вот такое объявление вектора:

vector::vector(size_type n, const string& val = string());

Честно говоря, я вообще не понимаю что тут происходит, кроме того, что я собственно объявляю вектор. Прошу, объясните, пожалуйста!

К тому же выдаёт ещё вот такую ошибку:

[Error] 'template<class _Tp, class _Alloc> class std::vector' used without template arguments

Насколько я понимаю, нужно добавить template <что-то> перед функцией, но я не совсем понимаю что именно.

Спасибо всем, кто объяснит!


Ответы (3 шт):

Автор решения: Zhihar

Ну как я понимаю вектор-то содержит элементы какого-то типа и вы должны указать, что это за тип:

Вектор строк:

vector<string> arr1;

Вектор целых чисел

vector<int> arr2;

Вектор векторов букв

vector<vector<char>> arr3;

Шаблоны - это такие конструкции, в которых не определены типы. (например, если у вас класс для int и для float делает ровно одно и то же, то зачем вам дублировать код? Вы пишите один код на несколько типов.)

→ Ссылка
Автор решения: Стас

Вектор (простыми словами) можно представить как динамический массив. Когда вы определяете массив, вы присваиваете ему тип данных. Например

int* array = new int[128];

А теперь вы пытаетесь создать вектор, но почему то решаете, что тип данных ему не нужен.

vector::vector(size_type n, const string& val = string());

Это просто конструктор класса, без заполнения шаблона его создать не получится.


Вектору тип данных присваивается через шаблон:

// Определение вектора из заголовочного файла vector
template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
    class vector : protected _Vector_base<_Tp, _Alloc>

В качестве первого аргумента передаётся тип данных, который должен хранить вектор. Вторым аргументом распределитель памяти (если второго аргумента нет - используется распределитель по умолчанию).


Например, создадим вектор целых чисел с размером в 10 ячеек:

std::vector<int> vec(10);

Вы можете по необходимости менять его размер с помощью функции resize. Но не забывайте, что перераспределение памяти это дорогостоящая в плане времени выполнения операция, и если количество элементов известно заранее лучше сделать вектор сразу нужно размера (или использовать vector::reserve)


Вы также можете передавать в конструктор значение, которым должен быть инициализирован только что созданный вектор.

Например:

std::vector<int> vec(10, 2);

создаст вектор из 10 элементов, заполненный двойками.


Я здесь рассказал только самое начало, если интересно подробнее: cppreference

→ Ссылка
Автор решения: Konstantin_SH

Давайте для начала разберем, что такое шаблоны.

Шабло́ны — средство языка C++, предназначенное для кодирования обобщённых алгоритмов, без привязки к некоторым параметрам. В C++ возможно создание шаблонов функций и классов.

Шаблон функции:

template <typename T>
void swap (T& x, T& y){
// тело функции
T temp = x;
x = y;
y = temp;
}
 

Этот шаблон принимает две ссылки на обобщенный тип T и переставляет значения под ссылками местами. То есть мы можем написать

int main (){
int x = 5;
int y = 12;

std::cout << "x = " << x << "\t y =" << y << endl;

double k =9.4;

double j =45.22;

std::cout << "j = " << j << "\t k =" << k << endl;
swap(x, y);
std::cout << "x = " << x << "\t y =" << y << endl;
swap(k, j);
std::cout << "j = " << j << "\t k =" << k << endl;

return 0;
}

Что происходит на этапе компиляции:

Компилятор : видит, что swap шаблонная. То есть ее можно вызывать от любых переменных с одинаковым типом, но тип не указан.

У компилятора : есть сложная система правил шаблонного вывода, которая в конечном счете подскажет ему какой тип вместо T подставить.

Компилятор : Подставит нужный тип. Вызовет функцию с нужным типом.

Чтобы это быстрее работало можно написать:

int main (){
int x = 5;
int y = 12;

swap <int>(x, y);
return 0;
}

Тут мы явно указываем компилятору, что хотим вызвать void swap (int x, int y);

Можно вызвать нашу swap так :

int main (){
int x = 5;
int y = 12;

swap <double>(x, y);
return 0;
}

Тогда компилятор увидит, что мы хотим вызвать void swap (doublle x, double y);, преобразует int x; int y в double x; double y и вызовет void swap (doublle x, double y); Но явно тип шаблонного параметра в случае с функциями указывают редко.

Теперь рассмотрим шаблон класса (и вспомним, что std::vector тоже шаблонный класс)

template <typename T>
class myArray {
// Поля класса
private :

int m_length;
T* m_data;

// Конструкторы класса

public:
    Array()
    {
        m_length = 0;
        m_data = nullptr;
    }
  Array(int length)
    {
        m_data = new T[length];
        m_length = length;
    }
 
    ~Array()
    {
        delete[] m_data;
    }
 
    void Erase()
    {
        delete[] m_data;
        // Присваиваем значение nullptr для m_data, чтобы на выходе не получить висячий указатель!
        m_data = nullptr;
        m_length = 0;
    }
 
 
    T& operator[](int index)
    {
        assert(index >= 0 && index < m_length);
        return m_data[index];
    }
 
    // Длина массива всегда является целочисленным значением, она не зависит от типа элементов массива
    int getLength(); // определяем метод и шаблон метода getLength() ниже
};
 
template <typename T> // метод, определенный вне тела класса, нуждается в собственном определении шаблона метода
int Array<T>::getLength() { return m_length; }  
}

Теперь мы можем написать:

int main()
{
    Array<int> intArray(10);
    Array<double> doubleArray(10);
 
    for (int count = 0; count < intArray.getLength(); ++count)
    {
        intArray[count] = count;
        doubleArray[count] = count + 0.5;
    }
 
    for (int count = intArray.getLength()-1; count >= 0; --count)
        std::cout << intArray[count] << "\t" << doubleArray[count] << '\n';
 
    return 0;
}

Зачем мы явно указывали тип тут?

Array<int> intArray(10);
Array<double> doubleArray(10);

и почему не можем написать

Array array (20);

Потому что на выделение памяти через new (malloc, calloc)

Array(int length)
    {
        m_data = new T[length];
        m_length = length;
    }

Эта самая сложная система шаблонного вывода не рассчитана и может работать только с примитивами. Компилятор не может сам определить массив какого типа мы хотим получить и поэтому в сообщении

[Error] 'template<class _Tp, class _Alloc> class Array' used without template arguments

Просит нас явно указать тип.

С вектором то же самое.

→ Ссылка