针对 resize() 循环推回 + 迭代器

发布于 2024-07-10 09:46:48 字数 1577 浏览 7 评论 0原文

简单的问题; 什么更好,为什么?



    out.resize( in.size() );
    T1::iterator outit = out.begin();
    for( inIt = in.begin() to end, ++inIt, ++outIt )
       *outit = *inIt
OR

    out.erase();
    for( inIt = in.begin() to end, ++inIt )
        out.push_back( inIt );


我假设 Push_back 中隐含的内存分配值得避免,但想确定一下。

谢谢

编辑: 感谢大家提出的建议;)。 我正在使用的实际代码是:


template//can't stop the browser ignoring th class T1, class T2 in angle brackets
bool asciihex( T1& out, const T2& in )
{
    //out.erase();
    out.resize( in.size() / 2 );
    if( std::distance( in.begin(), in.end() ) % 2 )//use distance rather than size to minimise the requirements on T2?
        return false;
    for( T2::const_iterator it = in.begin(); it != in.end(); it += 2 )
    {
        out.push_back(((( (*it > '9' ? *it - 0x07 : *it)  - 0x30)  '9' ? *(it+1) - 0x07 : *(it+1)) - 0x30) & 0x000f));
    }
    return true;
}

template
bool asciihex( T1& out, const T2& in )
{
    size_t size = in.size();
    if( size % 2 )//use distance rather than size to minimise the requirements on T2?
        return false;
    out.resize( size / 2 );
    T1::iterator outit = out.begin();
    for( T2::const_iterator it = in.begin(); it != in.end(); it += 2, ++outit )
    {
        *outit = ((( (*it > '9' ? *it - 0x07 : *it)  - 0x30)  '9' ? *(it+1) - 0x07 : *(it+1)) - 0x30) & 0x000f);
    }
    return true;
}

编辑:我已将 Push_back 标记为答案,因为它似乎是共识,因此对于遇到相同问题的其他人更有用。 然而,我最终使用了迭代器方法,因为我感兴趣的容器类之一不支持push_back...里程有所不同。

Simple question; what's better and why?



    out.resize( in.size() );
    T1::iterator outit = out.begin();
    for( inIt = in.begin() to end, ++inIt, ++outIt )
       *outit = *inIt
OR

    out.erase();
    for( inIt = in.begin() to end, ++inIt )
        out.push_back( inIt );


I'm assuming the memory assignment implicit in push_back is worth avoiding but want to make sure.

Thanks

EDIT:
Thanks for the out = in suggestions guys ;). The actual code I'm playing with is:


template//can't stop the browser ignoring th class T1, class T2 in angle brackets
bool asciihex( T1& out, const T2& in )
{
    //out.erase();
    out.resize( in.size() / 2 );
    if( std::distance( in.begin(), in.end() ) % 2 )//use distance rather than size to minimise the requirements on T2?
        return false;
    for( T2::const_iterator it = in.begin(); it != in.end(); it += 2 )
    {
        out.push_back(((( (*it > '9' ? *it - 0x07 : *it)  - 0x30)  '9' ? *(it+1) - 0x07 : *(it+1)) - 0x30) & 0x000f));
    }
    return true;
}

template
bool asciihex( T1& out, const T2& in )
{
    size_t size = in.size();
    if( size % 2 )//use distance rather than size to minimise the requirements on T2?
        return false;
    out.resize( size / 2 );
    T1::iterator outit = out.begin();
    for( T2::const_iterator it = in.begin(); it != in.end(); it += 2, ++outit )
    {
        *outit = ((( (*it > '9' ? *it - 0x07 : *it)  - 0x30)  '9' ? *(it+1) - 0x07 : *(it+1)) - 0x30) & 0x000f);
    }
    return true;
}

Edit: I've marked push_back as the answer as it seems to be the consensus and, therefore, more useful to anyone else with the same problem. However I have ended up using the iterator method as one of the container classes I'm interested in doesn't support push_back... mileage varies.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

回忆凄美了谁 2024-07-17 09:46:48

第二个,如果您担心多个扩展,请使用 out.reserve()。 添加到向量的正确答案几乎总是push_back或back_inserter,这避免了使用其他方法时必须注意的一些可能的问题(例如异常保证、构造函数、写到末尾)。

The second, and if you're concerned about multiple extensions use out.reserve(). The right answer to adding to a vector is almost always push_back or back_inserter, which avoid some possible problems (exception guarantees, constructors, writing past the end, for example) that you'd have to pay attention to with other methods.

骑趴 2024-07-17 09:46:48

第二个,只要你先预留合适的容量就可以了。

我看到的一个问题(除了风格之外)是,在第一个问题中,如果您的复制分配抛出异常,您已经采取了一项应该为您提供强有力保证的操作,并用它来提供不保证。

The second one, as long as you reserve the right capacity first.

One problem I see (apart from style) is that in the first one, if your copy assignment throws, you have taken an operation that should give you the strong guarantee, and used it to give no guarantee.

动听の歌 2024-07-17 09:46:48

如果您关心保留 in ,则执行以下操作:

out = in;

如果您不介意,则执行以下操作:

std::swap(out, in);

如果 out 和 in 是不同类型的容器,则尝试以下操作:

out.erase(out.begin(), out.end());
// if it's a vector or other contiguous memory container, you'll want to reserve first
// out.reserve(in.size());
std::copy(in.begin(), in.end(), back_inserter(out));

If you care about preserving in then do:

out = in;

If you don't, then do:

std::swap(out, in);

If out and in are different types of containers, then try this:

out.erase(out.begin(), out.end());
// if it's a vector or other contiguous memory container, you'll want to reserve first
// out.reserve(in.size());
std::copy(in.begin(), in.end(), back_inserter(out));
一场信仰旅途 2024-07-17 09:46:48

那么这有什么问题呢?

out = in;

您不认为这会是最好的行为吗? 如果没有,那就糟糕了。

另外,你的两个代码示例应该是

out.resize( in.size() );
T1::iterator outIt = out.begin();
for( T1::iterator inIt = in.begin(); inIt != in.end(); ++inIt, ++outIt )
   *outIt = *inIt;

out.erase(out.begin(), out.end());
for( T1::iterator inIt = in.begin(); inIt != in.end(); ++inIt )
    out.push_back( *inIt );

So what's wrong with this?

out = in;

Don't you think that'd have the best possible behavior? If it doesn't, that sucks.

Also, your two code examples should be

out.resize( in.size() );
T1::iterator outIt = out.begin();
for( T1::iterator inIt = in.begin(); inIt != in.end(); ++inIt, ++outIt )
   *outIt = *inIt;

and

out.erase(out.begin(), out.end());
for( T1::iterator inIt = in.begin(); inIt != in.end(); ++inIt )
    out.push_back( *inIt );
苏佲洛 2024-07-17 09:46:48

如果您正在处理简单的值,例如整数或双精度数,那么调整大小并设置或保留和push_back并不重要(性能方面)。

如果您正在处理具有重要构造函数的更复杂的对象,最好使用第二种基于 Push_back 的方法。

如果您的对象没有有意义的默认构造函数,那么 Push_back 方法是唯一有效的技术。

If you are dealing with simple values like integers or doubles it will not matter (performance wise) if you resize and set or reserve and push_back.

If you are dealing with more complex objects that have a significant constructor it is better to use the second push_back based method.

If you objects do not have a meaningful default constructor then the push_back approach is the only technique that works.

烟若柳尘 2024-07-17 09:46:48

我遇到过一种情况,与在调整大小的向量上使用 [] 运算符的解决方案相比,基于 push_back 的解决方案的性能更差。 造成差异的原因是每次执行 push_back 时检查向量是否需要扩展其容量的开销。

更糟糕的是,编译器决定无法内联对 push_back 的调用,但它确实将保留逻辑内联到 push_back 方法中。 这带来了函数调用的开销,并且调用的函数不必要地大。 即使经过一些force_inline按摩,它也没有基于[]运算符的循环那么快。

基于迭代器或 [] 运算符的循环除了写入值之外不会执行任何操作,至少在使用简单类型时不会。 如果使用更高级的类型,调整向量大小时默认构造函数的成本可能会破坏潜在的胜利。

无论如何,如果您的程序将大部分时间花费在此类循环中,我绝对认为您应该对不同的解决方案进行基准测试,并查看使用其中一种解决方案是否可以获得任何性能。 如果您没有在您描述的函数中花费大量的执行时间,那么您不应该关心这篇文章:)

I had a situation where I got worse performance in push_back-based solution compared to one using the [] operator on a resized vector. The cause of the difference was the overhead in checking whether the vector needs to expand its capacity every time it was doing a push_back.

What made it even worse was that the compiler decided it couldn't inline the call to push_back, but it did inline the reserve-logic into the push_back method. This gave the overhead of a function call and the function invoked was unnecessary large. Even after some force_inline massage, it wasn't as fast as the loop based on the [] operator.

A loop based on iterators or the [] operator won't do anything but writing the value, at least not when working with simple types. If working with more advanced types, the cost of the default constructor when resizing the vector may ruin the potential wins.

Anyway, if your program spends most of its time in these kinds of loop I definitely think you should benchmark the different solutions and see if there are any performance to gain by using one of the solutions. If you are not spending considerable amount of your execution time in the function you described, you shouldn't care about this post :)

妄想挽回 2024-07-17 09:46:48

与数组分配相比,我更喜欢 Push_back,因为无论有没有随机访问迭代器,push_back 都可以工作。 数组赋值需要它们。 如果您现在强制使用 randomaccessiterators,则将来将无法轻松更改容器。 当然,为了避免调整大小问题,您可以调用 vector::capacity 而不是调整大小。

I prefer push_back over array assignment as push_back will work with or without randomaccessiterators. Array assignment requires them. If you force randomaccessiterators now you can't easily change the container in the future. Of course, to avoid resize issues you call vector::capacity instead of resize.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文