Вектор преобразует все отрицательные значения в ноль

Я сделал вектор постоянного размера, чтобы сохранить отрицательные значения, а затем распечатать значения, которые у меня есть, были нулями. Я просто хочу знать, почему он не хранит отрицательные значения.

#include <iostream>
#include <vector>

int main() {
    std::vector<int> v(5);
    v.push_back(-1);
    v.push_back(-2);
    v.push_back(-3);
    v.push_back(-4);
    v.push_back(-5);

    for (int i=0; i<5; i++)
       std::cout << v[i] << " ";  // All I got was zeroes
}

Ответы

Ответ 1

Это потому, что push_back помещает новые элементы в конец вектора.

Вы можете увидеть эффект, запустив i до 9: отрицательные числа будут занимать v[5] - v[9].

Пишу

std::vector<int> v{-1, -2, -3, -4, -5};

вместо этого является особенно элегантным решением.

Ответ 2

Конструктор, который вы вызываете, заполняет первые 5 элементов нулями, см. Здесь (№ 3 в списке перегрузок):

Создает контейнер с установленными по умолчанию экземплярами T

(где "инсталлированный по умолчанию экземпляр" для int равен 0). То, что вы, возможно, хотели

std::vector<int> v;

v.reserve(5); /* Prevent unnecessary allocations as you know the desired size. */

v.push_back(-1);
/* ... */

Альтернативой, использующей исходный вызов конструктора, является

#include <numeric>

std::vector<int> v(5);

std::iota(v.rbegin(), v.rend(), -v.size());

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

Ответ 3

Это случай, когда принцип DRY поможет вам понять вашу ошибку.

vector<int> v(5);

...

for(int i=0;i<5;i++)

Здесь вы создаете массив, для которого вы считаете, что зарезервируете пространство для 5 элементов. Затем вы вставляете эти 5 элементов. После этого вы захотите распечатать содержимое всего массива, но вместо того, чтобы просто писать v.size(), вы повторили 5, так что ваш код теперь читается как "Печать первых пяти элементов v ", а не "Печать всех элементов" of v ".

Если вы вместо этого напишите, что вы имеете в виду, вы увидите, что в массиве фактически есть 10 элементов, а не 5.

BTW, поскольку С++ 11 вы можете прокручивать все элементы более простым способом:

for(int x : v)

или, если элементы были более дорогими по цене, вы могли бы использовать ссылки на элементы, даже auto -type ссылки:

for(auto& x : v)

Этот новый for синтаксиса -loop называется циклом, основанным for диапазоне.

Ответ 4

Вы можете считать vector гибкой версией примитивного массива в C/C++. Когда вы инициализируете vector размером n, построенный vector имеет размер n (или может быть больше в памяти, но вы не знаете, поскольку он неявно обрабатывается компилятором). Обратите внимание, что здесь n представляет количество записей, но не фактическое использование памяти (т.е. байты). Если вы не инициализируете его параметром размера, vector пуст с размером 0, но в памяти он будет иметь неявный размер памяти по умолчанию.

Скажем, ваш текущий vector имеет размер 5. И вы хотите push_back() в другом элементе, тогда vector внутри перераспределит весь массив в новую ячейку памяти, которая может содержать все свои старые записи, а также новую. Поэтому вам не нужно перераспределять память вручную самостоятельно, как то, что вы должны делать в C.

Здесь, в вашем примере, чтобы заполнить эти 5 отрицательных целых чисел в вашем vector, существует несколько способов.

1) Вы можете инициализировать vector без указания размера. И затем нажмите каждый элемент, который вы хотите.

vector<int> v;
for (int i = -1; i >= -5; --i) {
    v.push_back(i);
}

2) Вы можете инициализировать vector на своем пути с помощью этого параметра размера. А затем назначьте их новыми значениями.

vector<int> v(5);
for (int i = 0; i < v.size(); ++i) {
    v[i] = -i;
}

3) Вы также можете инициализировать vector с этими записями при его построении.

    vector<int> v{-1, -2, -3, -4, -5};
or  vector<int> v = {-1, -2, -3, -4, -5};

Ответ 5

Когда вы объявили вектор с

std::vector<int> v(5);

Вы сделали v хранит пять 4-байтовых пробелов в памяти (предполагая, что int = 4 байта в вашей системе), и по умолчанию все эти 4-байтовые пробелы хранят биты, представляющие 0. Затем вы нажали еще 5 целых чисел (-1, -2, -3, -4, -5) на конец вектора с:

v.push_back(-1);
v.push_back(-2);
v.push_back(-3);
v.push_back(-4);
v.push_back(-5);

В этот момент вектор имеет 10 элементов, первые пять - неизвестные ints, которые хранят 0 в экземпляре, в котором вы запускали программу. Поскольку ваш цикл for печатает первые пять элементов в векторе, поэтому он печатает все 0.