【问题标题】:What are your favorite C++ idioms? [duplicate]你最喜欢的 C++ 习语是什么? [复制]
【发布时间】:2011-05-24 05:11:04
【问题描述】:

可能重复:
What are your favorite C++ Coding Style idioms

亲爱的 C++ 粉丝,

您能在这里列出您最喜欢的 C++ 习语吗?最好列出那些有用但不为人所知的。

首先,我放了一个:

为了避免繁琐的重复 for (size_t i = 0; i < n; ++i) {...} ,我使用了这样的宏:

#define LOOP(n) for (size_t _i = 0; _i < n; ++_i)

_i 是 bind 使用的占位符。

所以我可以写:

vector<int> coll(100);
LOOP (100)
{
    coll[_i] = _i;
}

LOOP (100)
{
    auto a = _i;
    LOOP (100)
    {
        auto b = _i;
        cout << a << b;
    }
}

【问题讨论】:

  • 做你的榜样:这是你的 IDE 应该帮助你的东西,而不是晦涩的宏。
  • +1 表示一个体面的问题,但 -1 表示一个糟糕的、糟糕的例子。净零票:)
  • 可能有很多重复:*.com/questions/1759613/…*.com/questions/2096515/…*.com/questions/2345177/basic-c-idioms-techniques。 OP 的示例可能更像是一个 个人 习语,而不是普遍接受的 C++ 习语?
  • @UncleBens,是的,这是我的个人习惯。我认为不为人所知的个人习语可能更有趣。
  • 如果你需要两个嵌套的for循环怎么办?使用你的宏,占位符变量会发生冲突。

标签: c++ idioms


【解决方案1】:

RAII 是我的首选。很多情况下它只是派上用场......

像 Andrei Alexandrescu 的 libloki 这样的通用实现最有用。

【讨论】:

  • +1 RAII 是我真正希望其他语言支持的 C++ 之一。
  • +1 表示 RAII 和应答速度。
【解决方案2】:

【讨论】:

  • 我就知道你会这么说。 :D
  • @Nawaz :我想说 RAII,但有人已经提到过。我必须命名一些不同的
  • @Nawaz:有人一直在看 Dredd 法官 :)
【解决方案3】:

好问题,但我认为你的例子是一个坏的!你的LOOP 宏并没有让任何事情变得更清楚——它实际上向不使用你的宏的程序员隐藏了你的意图,它甚至看起来不像 C++——我对你的 sn-p 的第一反应是“即使C++?”或“普通的for 有什么问题?”。一遍又一遍地编写循环可能很乏味,但我们都知道每个人在阅读和维护代码上花费的时间比最初编写代码要多得多,所以写一个完整的 for 并不会浪费时间,而且它更清晰。您可以继续争论您的观点,但您应该知道,以这种方式使用宏不是被广泛接受的技术 - 其他人查看您的代码也会对您提出异议。

无论如何,要添加一个实际的答案 - 我在 C++0x 中最喜欢的成语是 unique_ptr 的向量:

std::vector<std::unique_ptr<T>> my_container;

它有以下优点——本质上是一个安全的指针向量:

  • 它在 O(1) 时间内提供随机访问
  • 保证元素即使在重新分配时也不会在内存中移动(因此您可以安全地获取Ts 的地址并存储它们)
  • 对于排序等任务来说速度很快(只是洗牌一些指针,而不是复制重量级对象)
  • 异常安全并有助于防止内存泄漏 - 元素上的 erase() 也会释放内存
  • 灵活 - 您可以将 std::move() 指针移出容器并将它们放在其他地方

它确实有一两个缺点:

  • 每个元素都分配在堆上,如果添加/删除大量元素,可能会对性能产生影响,而且元素在内存中可能相距很远,从而失去缓存位置
  • 迭代需要双重间接 (*i)-&gt;member 语法 - 但我认为这没什么大不了的

但是,特别是对于重量级的物体,我认为它几乎是一个理想的容器。

【讨论】:

    【解决方案4】:

    RAII + 如果需要确切的生命周期范围,则打开一个嵌套块:

    Lock lock(this);
    ResourceHolder resource(findResource());
    WorkerHolder worker(resource);
    if (!worker)
        return false; // frees the resource and unlocks the lock
    {
        WorkAssignment assignment(worker);
        assignment.Execute();
    } // assignment cleaned up even in case of exception
    ...
    

    【讨论】: