C++ 设置*两个*元素和std::vector的初始容量

C++ 设置*两个*元素和std::vector的初始容量,c++,c++11,vector,C++,C++11,Vector,我在书中读到,std::vector的初始容量不能由其构造函数控制。如果您知道它的大小在运行时是恒定的,那么设置它的最佳方法似乎是: const int size; std::vector<T> v; v.reserve(size); 或 std::向量v(大小,T());//可能分配的内存比我需要的多。。 v、 收缩到适合();/。。然后立即解除分配(无意义) 最接近我理想的是什么: std::vector<T> v(size, T(), /*capacity =*

我在书中读到,std::vector的初始容量不能由其构造函数控制。如果您知道它的大小在运行时是恒定的,那么设置它的最佳方法似乎是:

const int size;
std::vector<T> v;
v.reserve(size);

std::向量v(大小,T());//可能分配的内存比我需要的多。。
v、 收缩到适合();/。。然后立即解除分配(无意义)
最接近我理想的是什么:

std::vector<T> v(size, T(), /*capacity =*/ size);
std::vector v(大小,T(),/*容量=*/size);

[编辑]:从您的回答可以看出,我更确切地需要的是
v
填充
size
实例
T
,每个构建使用
T
的默认构造函数,而不是复制。当编译时不知道
大小时,我不能使用初始值设定项列表,我该怎么办


奖金:顺便问一下,为什么没有办法选择向量的初始容量?

首先奖金:

好处:顺便问一下,为什么没有办法选择向量的初始容量

因为课程的设计者从来没有考虑过它的重要性


据我所知,在以下情况下没有实施:

std::vector<T> v(size, T());
标准没有保证它能保持。但这似乎是事实上的标准

然而,人们无法将这一点知识转移到
std::string


如果您想在构建之后积极地要求
容量()==size()
,您可以使用
收缩以适应()
。这就是说,
shorn\u to_fit()
标准不能保证它能正常工作,如果它真的有任何作用,它会暂时使您的内存需求翻倍。这种用法可能类似于:

std::vector<T> v(size, T());
if (v.capacity() > v.size())
    v.shrink_to_fit(); // If executed and successful, this will allocate a new buffer
if (v.capacity() > v.size())
    // now what?
向量v(大小,T()); 如果(v.capacity()>v.size()) v、 将_收缩到_-fit();//如果执行成功,将分配一个新的缓冲区 如果(v.capacity()>v.size()) //现在怎么办?


使用
reserve()
不再有效。在
reserve()
之后,如果发生重新分配,
capacity()
大于或等于
reserve
的参数;否则等于前面的
capacity()
值。

不清楚所有元素的构造方式。假设您希望向量具有
n
元素和容量
所需容量
,这可能等于
n

如果希望
n
元素相同,请尝试以下操作:

std::vector<T> v(n, t);  // creates n copies of the value t.
v.reserve(desired_capacity);
可能性的清单还在继续;有关更多信息,请参阅。使用“就地”构造意味着您可以使用不可复制构造的类型填充向量

另一种方法是使用不可复制的类型填充向量,即重复使用emplace_back:

std::vector<T> v;
v.reserve(n); 
for (int i = 0; i < n; ++i)
{
   v.emplace_back(x, y, z);  // Construct T(x, y, z) in-place
}

您可以使用容量和初始值构建向量

std::vector<std::string> vs(5, "abc");
std::vector<std::pair<int, int>> x(6, std::pair<int,int>(1, 2));
标准:向量vs(5,“abc”); std::向量x(6,std::对(1,2));
指定初始大小的向量构造函数无论如何都必须迭代以初始化元素。即使没有显式迭代初始化元素的代码,这也是向量构造函数中发生的情况。所以我不认为这样做有什么问题:

template<typename T, typename... Args>
std::vector<T> create_vector_with_capacity(size_t size, size_t capacity, Args... args)
{
    std::vector<T> v;
    v.reserve(capacity);

    for (size_t i = 0; i != size; ++i)
        v.emplace_back( args... );

    return v;
}
模板
std::vector创建带有容量的向量(大小、容量、参数…参数)
{
std::向量v;
v、 储备(容量);
对于(大小i=0;i!=size;++i)
v、 后置炮台(args…);
返回v;
}
示例用法:

std::vector<std::string> vec = create_vector_with_capacity<std::string>(5, 20, "foo");
std::vector vec=创建容量为(5,20,“foo”)的向量;
std::vector
的移动语义确保,即使禁用了复制省略且
T
不可移动,也不会复制向量,即使它是通过值返回的

此版本使用
args
(如果未提供任何args,则使用默认构造函数)就地构造每个元素;或者,您可以替换
Args。。。args
使用
T&&T=T()
push\u back
,将从传入的一个元素(可能是临时的)复制所有元素

注意:事实上,该标准并不能绝对保证移动向量时保持其容量(我无论如何都不知道);如果您的实现没有做到这一点,或者如果您确实希望保证容量保留,则不要返回
v
,而是将其设置为调用方必须提供空向量的引用传递参数。

您可以执行以下操作:

std::vector<T> v;
v.reserve(size); // don't construct any T. v.size() == 0.
v.resize(size);  // do construct T.
std::vector v;
v、 保留地(大小);//不要构造任何t.v.size()==0。
v、 调整大小(大小);//不要构造T。

太棒了!那么我应该自信吗?或者使用
v.shrink\u to\u fit()
只是为了清楚起见,它无论如何都不会执行?请不要使用
shrink\u to\u fit
。马萨:好的,
v.reserve(大小)
。那么它会不会执行到零呢?请告诉我们为什么^是,
v.reserve(x)
如果
x
,则不会调整向量大小。这是一件好事,因为在C++标准中没有功能的重新分配;code>std::vector
改变大小意味着
v.size()
copies…@HowardHinnant:好吧,那我们就相信实现吧。:)非常感谢。如果您需要一个精确且大小恒定的数组,请使用。@RetiredInja:我不能,因为正如我所说的,大小在运行时是已知的。啊,对不起,我错过了,使用
std::vector v;v、 储备(规模);对于(T:v)T=T()循环无效,因为
v
为空。(无论如何,你会修改一份
v
内容)。嘿,我认为你的答案,甚至离这个主题的
std::vector::capacity
问题更远,结果更接近我的实际问题。正如你所说,我真正需要的是“用不可复制构造的类型填充向量”。即:调用默认构造函数
size
次。但我
std::vector<T> v;
v.reserve(n); 
for (int i = 0; i < n; ++i)
{
   v.emplace_back(x, y, z);  // Construct T(x, y, z) in-place
}
for(T t : v) t = T();    
// almost certainly want for (T& t : v) ...
// in order to get references to modify vector elements.
std::vector<std::string> vs(5, "abc");
std::vector<std::pair<int, int>> x(6, std::pair<int,int>(1, 2));
template<typename T, typename... Args>
std::vector<T> create_vector_with_capacity(size_t size, size_t capacity, Args... args)
{
    std::vector<T> v;
    v.reserve(capacity);

    for (size_t i = 0; i != size; ++i)
        v.emplace_back( args... );

    return v;
}
std::vector<std::string> vec = create_vector_with_capacity<std::string>(5, 20, "foo");
std::vector<T> v;
v.reserve(size); // don't construct any T. v.size() == 0.
v.resize(size);  // do construct T.