Не разрешать добавление большего количества элементов в вектор - PullRequest
0 голосов
/ 28 октября 2018

Мне нужно зарезервировать x количество элементов в std::vector, скажем, 10. Затем мне нужно записать в него некоторое число y, скажем, 5 (большую часть времени y

Пример: Скажем, я выделил 10 элементов

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

Но я только заполняю 7 из этих элементов

for (unsigned i = 0; i<7; i++)
  v[i] = i;

Как я могу сказать, что 7 элементов были заполнены, и у меня еще есть 3 доступных?

Я пытался бежать v.size() и v.capacity() но оба возвращают 10.

Ответы [ 3 ]

0 голосов
/ 28 октября 2018

Вы имеете в виду что-то подобное?

std::vector<int> a; // dont allocate anything

// allocate memory for 10 elements, 
// but dont actually create them. a.size() is still 0.
a.reserve(10); 

for(std::size_t i = 0; i < 7; ++i) {
    // copy i to a new element at the back 
    // of the vector. This will never reallocate 
    // memory, as long as at most 10 elements 
    // are pushed:
    a.push_back(i); 
}
// a.size() is now 7
0 голосов
/ 28 октября 2018

Мне нужно зарезервировать x количество элементов в std::vector, скажем, 10.

std::vector имеет reserve() метод для этой конкретной цели.

Затем мне нужно записать в него некоторое количество значений y, скажем, 5 (большую часть времени y

Вектор capacity() - это количество выделенных элементов, в то время как size() - это количество выделенных элементов, которые были заполнены значениями. Итак, capacity() - size() - это количество доступных элементов, которые были выделены, но не назначены.

Я пытался запустить v.size() и v.capacity(), но оба возвращают 10.

Это потому, что вы вызываете конструктор vector, который выделяет AND, одновременно заполняет элементы. Вы создаете vector с именем v, в котором 10 элементов заполнены 0. Поэтому size() и capacity() равны 10. Ни один из конструкторов не будет делать то, что вы хотите. Вам нужно использовать конструктор по умолчанию и затем вызывать reserve() отдельно, например:

std::vector<int> v;
v.reserve(10); // capacity = 10

for (int i = 0; i < 7; ++i)
    v.push_back(i);

size_t filled = v.size(); // size = 7
size_t available = v.capacity() - v.size(); // available = 3
0 голосов
/ 28 октября 2018

Редактировать: Я добавил метод, используя std::unique_ptr.


Если вам доступен C ++ 17, как насчет замены элементов v на std::optional<int> следующим образом?

#include <iostream>
#include <optional>
#include <vector>
#include <algorithm>

int main()
{
    std::vector<std::optional<int>> v(10);

    for (std::size_t i = 0; i<7; ++i){
        v[i] = i;
    }

    std::cout 
        << (v.size() - std::count(v.cbegin(), v.cend(), std::nullopt))
        << " elements have been filled and I still have "
        << std::count(v.cbegin(), v.cend(), std::nullopt) 
        << " available."
        << std::endl << std::endl;

    for(const auto v_i : v)
    {
        if(v_i.has_value()){        
            std::cout << v_i.value() << " ";
        }
    }

    return 0;
}

Но если вы ограничены более старой версией, я думаю, что std::unique_ptr будет решением. DEMO :

#include <iostream>
#include <memory>
#include <vector>
#include <algorithm>

int main()
{
    std::vector<std::unique_ptr<int>> v(10);

    for (std::size_t i = 0; i<7; ++i){
        v[i] = std::make_unique<int>(i);
    }

    std::cout 
        << (v.size() - std::count(v.cbegin(), v.cend(), nullptr))
        << " elements have been filled and I still have "
        << std::count(v.cbegin(), v.cend(), nullptr) 
        << " available."
        << std::endl << std::endl;

    for(const auto& v_i : v)
    {
        if(v_i){        
            std::cout << *v_i << " ";
        }
    }

    return 0;
}

Наконец, я нашел похожие подходы здесь .

...