的std ::矢量<>使用不初始化基元的resize()导出&转发construct_back

时间:2012-03-07 08:56:11

标签: c++ performance vector c++98

因此,在性能敏感的应用程序中需要它的大量案例,我终于挣扎着打破了骆驼。它需要在C ++ 98中编译,因为我们的平台中至少只有一个保证符合C ++ 98标准。

希望能够更清楚地了解我想要的东西。

示例:

// This will allocate storage for 1024, and then loop 1024 times touching all of it just to place a 0 in it 
std::vector< char > buffer( 1024 );
// Now read will write into that buffer, overwriting the 0s ( we payed for the fill unnecessarily ) 
buffer.resize( read( someSource, &buffer[0], buffer.size() ) );

这是常见的C接口,几乎与所有C库一起用于将数据写入缓冲区。在处理通常包含基元的缓冲区时会出现同样的问题。新的大小调整看起来像这样:

// Disabled for anything which doesn't pass boost::is_POD< T >, they get the standard version
void resize( size_t a_NewSize )
{
     reserve( a_NewSize );
     _end = _begin + a_NewSize;
}

construct_back将是一个转发构造函数,对于1个const参数,它看起来像这样(未经测试):

template< typename T1 >
void construct_back( const T1& a_Arg1 )
{
    if( capacity() <= size() ) // No room
         reserve( size() + 1 );
    // Construct in place using Ts constructor that accepts const T1&
    new (&(*end()) T( T1 );
    ++_end; // Account for new element
}

construct_back必须拥有所有可能数量的参数^ 2重载,这是在C ++ 98中完美转发的常见蛮力方法。

3 个答案:

答案 0 :(得分:3)

要在向量中预分配内存,请使用vector::reserve。这不仅适用于原始类型,也适用于所有类型。

要构建元素,您需要使用带有vector::emplace_back的C ++ 11或Boost.Containers提供的其中一个容器。

如果你需要延迟构造(因为你的构造函数很贵)std::vector<boost::optional>是一个很好的解决方案。

答案 1 :(得分:1)

您的编译器可能足够聪明以避免初始化。 (如果它是内联所有内容而你只在本地使用这个向量,那么推断初始化是过时的并不是太复杂。)

否则:

如果你非常关心性能,如果你还有一个固定大小的缓冲区,为什么不在堆栈上使用一个数组呢?即:

char buffer[1024];
size_t blen = read( someSource, buffer, sizeof(buffer) );

在这种情况下,您还可以避免间接到std::vector引入的堆。

你也可以围绕它建立自己的模板容器,即:

template<typename T = char, size_t MaxSize = 1024>
struct Buffer {
    static const size_t maxsize = MaxSize;
    typedef T type;
    type data[maxsize];
    size_t len;
    Buffer() : len(0) {}
};

并根据需要插入任何其他功能(使其成为STL容器)。

答案 2 :(得分:0)

v1.reserve( 200 );
使用预留可以减少调整大小的次数 在MSDN

了解有关保留的更多信息