gpt4 book ai didi

c++ - 使用 back_inserter() 或 inserter() 提高 std::copy() 的效率

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:19:03 25 4
gpt4 key购买 nike

back_inserterinsert_iterator 非常方便,但效率也很低!

例如,当您附加 char 时,当您复制时,每个元素都会有大量开销,在许多情况下,确实没有必要。

有没有办法让它们更有效率?

最佳答案

是的,您可以定义一个新版本的 std::copy,它可以劫持可优化调用。 :)

下面是一个针对 Visual C++ 和 GCC 的示例(或者“hack”,如果您更喜欢看到玻璃杯是半空的)。

在我的个人计算机上(我使用 VC++ 2010),下面的代码使调用速度十倍!
GCC 的基准也在这里,显示出 5 倍的差异:old version反对new version

但是你使用它之前:

请注意,这段代码假设容器提供了一个类似vector的接口(interface)

如目前所写,这仅适用于 C++11,因为它使用 type_traits header 的元编程功能优化复制操作将保留的情况异常安全。

如果您不需要异常安全(尽管在实际执行此操作之前您应该三思而后行),或者如果您有另一种检查此类数据类型的方法,那么您可以更改

typename enable_if<..., typename insert_iterator<C> >::type

到:

insert_iterator<C>

其余代码也适用于 C++03。

namespace std
{
template<class FwdIt, class C>
back_insert_iterator<C> copy(
FwdIt begin, FwdIt end, back_insert_iterator<C> it,
forward_iterator_tag * =
static_cast<typename iterator_traits<FwdIt>::iterator_category *>(0))
{
struct It : public back_insert_iterator<C>
{
using back_insert_iterator<C>::container;
static C &deref(C &c) { return c; }
static C &deref(C *c) { return *c; }
};
copy(begin, end, inserter(It::deref(static_cast<It &>(it).container),
It::deref(static_cast<It &>(it).container).end()));
return it;
}

template<class FwdIt, class C>
typename enable_if< // Only do this if it would be exception-safe!
is_nothrow_copy_constructible<typename C::value_type>::value &&
is_nothrow_copy_assignable<typename C::value_type>::value,
insert_iterator<C>
>::type copy(
FwdIt const &begin, FwdIt const &end,
insert_iterator<C> output,
forward_iterator_tag * = // only forward iterators
static_cast<typename iterator_traits<FwdIt>::iterator_category *>(0))
{
struct It : public insert_iterator<C>
{
using insert_iterator<C>::container; // protected -> public
using insert_iterator<C>::iter; // protected -> public
static C &deref(C &c) { return c; }
static C &deref(C *c) { return *c; }
};
It &it(static_cast<It &>(output));
typename C::iterator it_iter_end(It::deref(it.container).end());
{
// Convert iterators to offsets
typename C::size_type const iter_end_off =
std::distance(It::deref(it.container).begin(), it_iter_end);
typename iterator_traits<typename C::iterator>::difference_type off
= std::distance(It::deref(it.container).begin(), it.iter);

// Resize container
It::deref(it.container).resize(
It::deref(it.container).size() +
static_cast<typename C::size_type>(std::distance(begin, end)));

// Renormalize, in case invalidated
it.iter = It::deref(it.container).begin();
std::advance(it.iter, off);
it_iter_end = It::deref(it.container).begin();
std::advance(it_iter_end, iter_end_off);
}
typename C::iterator result
= copy_backward(it.iter, it_iter_end, It::deref(it.container).end());
copy_backward(begin, end, result);
return inserter(It::deref(it.container), result);
}
}

关于c++ - 使用 back_inserter() 或 inserter() 提高 std::copy() 的效率,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12327163/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com