Пожалуйста, обратитесь к обновленному и аннотированному примеру. Это может помочь уточнить:
#include <vector>
#include <stdexcept>
void f(int size)
{
// don't use using namespace standard at global scope.
// if you must use it, use it at the tightest possible scope
// for better, only bring in the names you need
using std::vector;
// creates an empty vector with size() == 0 and capacity() == 0
vector<int> v;
// this reserves storage, it does not create objects in v or extens its size()
v.reserve(size);
// v.capacity() is now >= size
// in this example, this step is actually un-necessary because...
// ... a resize will increase capacity() if necessary
v.resize(size);
// there is still possible UB here, if size == 0.
// we should check for that...
if (v.size() < 1)
throw std::out_of_range("size is less than 1");
v[0] = 1; // This is now OK
// ...which is essentially equivalent to this...
v.at(0) = 1;
// create an empty vector of vectors
// vv.size() == vv.capacity() == 0
vector<vector<int> > vv;
vv.reserve(size);
// now vv.size() == 0 and vv.capacity() >= size
// this would result in:
// vv.size() == 1, vv.capacity() >= max(vv.size(), size);
// vv.push_back(v); // everything is OK with this
if(1)
{
// at the moment, vv[0] results in UB because .size() is zero
// so lets's add an entry in vv
vv.resize(1);
// vv.size() == 1, vv.capacity() >= max(vv.size(), size);
// these are now valid
vv[0].push_back(1);
vv[0] = {1};
}
else
{
// this would also be ok
auto make_vector = [] {
auto va = vector<int>();
va.push_back(1);
return va;
};
vv.push_back(make_vector());
// as would this
vv.emplace_back(std::vector({1}));
}
}
int main() {
f(3);
}