用C ++做两次事的成语

时间:2012-05-22 19:25:12

标签: c++ idioms

有两种做法的共同习惯,如下列情况?

    for ( int i = 0; i < num_pairs; i++ ) {
        cards.push_back( Card(i) );
        cards.push_back( Card(i) );
    }

我觉得有一种更清晰的方法,就是引入一个从0到1计数的新循环变量,特别是因为除了计数之外它没有被使用。

    for ( int i = 0; i < num_pairs; i++ )
        for ( int j = 0; j < 2; j++ )
            cards.push_back( Card(i) );

Card只是我编写的一些课程,与问题无关。)

5 个答案:

答案 0 :(得分:10)

您可能希望使用fill_n

中的<algorithm>功能
for ( int i = 0; i < num_pairs; i++ )
    std::fill_n(std::back_inserter(cards), 2, Card(i));

答案 1 :(得分:6)

就我个人而言,我会留下它是怎么回事。它看起来干净,易于理解,而且非常易读。只需留下评论,提及你为什么要这样做两次(但无论如何都会这样做)。

答案 2 :(得分:5)

我有一些建议。有关我的建议,请参阅 last

  1. 在我看来insert(it, N , value)击败std::fill_n

    for ( int i = 0; i < num_pairs; i++ ) {
        cards.insert(cards.end(), 2, Card(i) );
    }
    
  2. 如果订单不重要,您只需生成一次卡片,然后在之后复制

    std::copy(cards.begin(), cards.end(), std::back_inserter(cards));
    
  3. 使用脏lambda和整数除法技巧。 警告这是过早优化的标志:没有充分理由降低可读性。

    std::vector<Card> cards(num_pairs * 2);
    int i = 0;
    std::generate_n(cards.begin(), num_pairs, [&i] () { return Card(i++/2); });
    

    (假设Card 默认可构建。如果不是,请使用cards.back_inserter()

  4. 我的推荐

    以下在表现和意图表达方面取得胜利:

    std::vector<Card> cards;
    cards.reserve(num_pairs*2);
    for (int i = 0; i < num_pairs; ++i)
    {
        cards.emplace_back(i);
        cards.emplace_back(i);
    }
    

答案 3 :(得分:1)

你正确使用将内部循环扩展为语句,因为使用另一个循环只有2次迭代会对性能造成不利影响。由于频繁jumps,第二个(嵌套循环)将执行缓慢。是否会有明显的差异完全取决于num_pairs

所以第一个对性能更好(但是增益可能是微不足道的)。这种扩展循环在编译器的术语中称为loop unwinding/unrolling。但是,这个术语不是在编程级别使用,因为通常只有编译器才能使代码更快。 Idioms肯定design notions可帮助程序员更好地编写&amp;高效的代码,更好地理解语言。

答案 4 :(得分:1)

如果你想经常这样做,写一点实用功能:

template<class F>
void repeat(unsigned times, F callback) {
  while (times--) callback();
}

// ...

for (int i = 0; i < num_pairs; i++) {
  repeat(2, [&] { cards.push_back(Card(i)); });
}

我在Ideone上写了一个例子。


您的第一种方法可能会让您未来的代码读者感到困惑。他们可能会认为代码偶然出现了两次。使用这样的函数可以避免这种混乱。

即使&gt;表现也会非常小。 0,因为编译器可能内联函数并完全优化小times'的循环。如果您担心性能,请首先进行基准测试。