Вектор преобразует все отрицательные значения в ноль
Я сделал вектор постоянного размера, чтобы сохранить отрицательные значения, а затем распечатать значения, которые у меня есть, были нулями. Я просто хочу знать, почему он не хранит отрицательные значения.
#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.