std :: vector <t> :: resize(n,val)是否足以进行初始化?</t>

时间:2015-01-13 14:35:29

标签: c++ c++11 vector initialization

这是一个特定于C ++ 11的问题。 假设我已经使用了向量std::vector<T> v,并且我想将其大小调整为使用现有值n初始化的T val元素。 (典型用例:vector是要回收的实例的成员。)

以下方式的优缺点是什么,哪种方式最有效?

1)std::vector<T>::resize( n, val )是否足以进行初始化?

v.clear();
v.resize( n, val );

2)如果没有,那么我认为以下是正确的?

v.clear();
v.resize(n);
std::fill( v.begin(), v.end(), val );

3)交换怎么样?

v.swap( std::vector<T>( n, val ) );

4 个答案:

答案 0 :(得分:8)

为什么不使用专为此工作设计的界面?

v.assign(n, val);

Documentation Here

答案 1 :(得分:5)

(4)

std::fill(v.begin(), std::min(v.begin() + n, v.end()), val);
v.resize(n, val);

如果T具有合适的分配行为,至少比构建新分配行为便宜,则使用(4)。这是T = int的情况(赋值和构造是相同的)和T = std :: string(赋值可以比构造更快,因为它可以使用现有缓冲区。)

如果T具有相同的分配和构造成本(例如T = int),那么(1)也可以用于清晰而不会损失性能。

如果无法分配T,或者由于某种原因,分配比构建(稀有)更昂贵,那么使用(1)

(1)可以通过使用v.assign(n, val);(kudos to @Casey)来简化

我不知道使用assign(4)在性能方面是否相同。我不知道分配是否(具有讽刺意味的是,给定名称)将新元素分配给现有元素,或者重新构建它们。

编辑:(4)可能的改进,我还没有测试过。它可以避免在矢量容量变化期间复制/移动的开销。

if (n <= v.capacity())
{
    std::fill(v.begin(), std::min(v.begin() + n, v.end()), val);
    v.resize(n, val);
}
else
{
    v.assign(n, val);
}

答案 2 :(得分:3)

(1)就够了。 (3)也有效。不同之处在于:(1)如果新尺寸小于电流,则不释放存储器。 (3)总是分配新的内存块并删除旧内存。

(2)通常比(1)慢,因为它首先默认构造元素,然后分配它们。如果T不是默认可构造的,它甚至可能无法编译。

答案 3 :(得分:3)

让我们将其分解以显示其中每一个之间的差异。我将n用作新尺寸,m用作旧尺寸。

1

v.clear();//keeps the same buffer, but calls the destructor on all the values
v.resize(n, val);//only makes a new buffer if the value is bigger, does no moves.

2

v.clear();//keeps the same buffer, but calls the destructor on all the values
v.resize(n);//initializes all the values to default
std::fill( v.begin(), v.end(), val );//initializes all the values again to the new value

3

v.swap( std::vector<T>( n, val ) );//calls destructor on all values in v, cannot reuse the buffer, initializes all the values to the new value

差异微妙但真实。 1 可以(但不保证)重用缓冲区,这可以节省内存开销。 2与1相同,但双重重新初始化。 3与1相同但不能重用缓冲区。

就我个人而言,我认为三者之间的差异在大多数情况下都过于微妙,而且1是最具可读性的。