2012-03-07 69 views
1

所以有很多情况下,它需要在性能敏感的应用程序,我终于在打破骆驼的秸秆背部。它需要在C++ 98中编译,因为我们至少有一个平台只能保证C++ 98的合规性。std :: vector <>派生与resize(),不初始化原语和转发construct_back

编辑希望能够更清楚我想要什么。

实施例:

// 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中完美转发的常见强力方法。

+0

它是你可以问的最简单的方法吗? – 2012-03-07 09:04:50

+0

@Ylisar我听到你的伴侣,似乎没有人理解你的问题。我引用这个http://stackoverflow.com/questions/1461276/stdvector-reserve-and-push-back-is-faster-than-resize-and-array-index-w,希望能让其他人更清楚。 – dcousens 2012-03-09 02:55:45

回答

3

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

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

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

+1

载体::储备预先分配,但有没有办法使用的内存没有先增加向量的大小,增加大小意味着初始化高达尺寸,这在我的经验中99%的时间,你不希望所有元素与原始做。 emplace_back看起来很有趣,但令人遗憾的是,我不能使用C++ 98中不存在的任何东西,忘记提及这一点。 – Ylisar 2012-03-07 09:07:04

+0

@Ylisar你应该在你的问题中提到这一点。这个要求是很重要的。对我来说,看起来你并不是在寻找一个矢量,而是一个'map '。同样,你指定的行为对于任何具有不平凡拷贝构造函数的东西都是不可实现的,这使得所有这些变得更加困难。 – pmr 2012-03-07 09:10:25

+0

我会尝试重新翻译,因为我显然不是很清楚。转发construct_back会使用新的位置,除非我错过了某些东西(尽管在C++ 98中需要提供所有可能的重载,通常在C++ 98中的转发限制),这很麻烦。我希望resize()变体所做的与储备完全相同,但同时也要修改其大小(当然,如果T不是原始的,那么这会给我们所有的地狱破坏带来成熟的机会,但是可以用disable_if来解决)。 – Ylisar 2012-03-07 09:24:37

0
v1.reserve(200); 

使用储备,可以减少调整 数量阅读更多关于准备金MSDN

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容器类)插入任何其他职能那里。

+0

在堆栈上使用缓冲区通常很好,但它有一些缺点。我想要的是或多或少的替代std :: vector <>。 – Ylisar 2012-03-09 12:21:18

相关问题