2

I need to reserve x number of elements in a std::vector, say 10. Then I need to write some y number of values into it, say 5 (most of the time y < x). Is there a way to say how many values have been written to it and how may are still available?

Example: Say I allocate 10 elements

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

But I only fill 7 of these elements

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

How can I tell that 7 elements have been filled and I still have 3 available?

I tried running v.size() and v.capacity() but both return 10.

flashburn
  • 4,180
  • 7
  • 54
  • 109
  • 2
    Consider using `std::vector::reserve` and `std::vector::push_back` methods. – 273K Oct 28 '18 at 05:03
  • 1
    *But I only fill 7 of these elements* -- What is your definition of "fill"? You declared a vector of 10 elements, all initialized to 0. If you want a vector with only 7 items, then create a vector with only 7 items. – PaulMcKenzie Oct 28 '18 at 05:07
  • @PaulMcKenzie My motivation is to reserve some space for some maximum number of elements. Actual number of elements can be less than maximum but never more. When I reserve 10 elements, I don't necessarily care if they are initialized to 0, but once I start inserting elements I want to know how many I've inserted. – flashburn Oct 28 '18 at 05:17
  • 2
    You didn't do any inserts in your example. Those "inserts" have already been done in the constructor. You construct a vector of 10 elements, you get 10 elements, so of course `v.size()` returns 10. Maybe your idea of what a vector is seems to be a bit flawed. – PaulMcKenzie Oct 28 '18 at 05:57
  • *But I only fill 7 of these elements* Nope. You *modify* 7 of these elements. `=` stands for assignment here. Assignment does not create, allocate, fill, ... its left hand side. It gives a new value to a thing that already exists. – n. m. could be an AI Oct 28 '18 at 06:53
  • `std::vector` is not designed to do that. You can **use** `std::vector` in your own class, and add all the frills that you want, while the vector member holds the data and manages its storage. – Pete Becker Oct 28 '18 at 14:46

3 Answers3

3

Do you mean something like this?

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
Chemistree
  • 432
  • 6
  • 11
1

Edit: I added a method using std::unique_ptr.


If C++17 is available to you, how about replacing v's elements by std::optional<int> as follows ?

#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;
}

But if you are constrained by an older version, I think that std::unique_ptr would be a solution. 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;
}

Finally, I found similar approaches here.

Hiroki
  • 2,780
  • 3
  • 12
  • 26
1

I need to reserve x number of elements in a std::vector, say 10.

std::vector has a reserve() method for that exact purpose.

Then I need to write some y number of values into it, say 5 (most of the time y < x). Is there a way to say how many values have been written to it and how may are still available?

The vector's capacity() is the number of elements have been allocated total, whereas its size() is the number of allocated elements that have been populated with values. So, capacity() - size() is the number of available elements that have been allocated but not assigned.

I tried running v.size() and v.capacity() but both return 10.

That is because you are calling the vector constructor that allocates AND populates elements at the same time. You are creating a vector named v that has 10 elements populated with 0. That is why size() and capacity() are both 10. None of the constructors will do what you want. You need to use the default constructor and then call reserve() separately, eg:

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
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770