代码之家  ›  专栏  ›  技术社区  ›  Lucas

包装STL习惯用法以提高可读性是个好主意吗?

  •  11
  • Lucas  · 技术社区  · 15 年前

    我目前正在研究一个C++项目,它需要尽可能少的外部依赖,因此我非常依赖STL和Boost。到现在为止,C++时代,我几乎一直生活在QT土地上。一般来说,我倾向于在可能的情况下使用C#和Python。

    今天我想看看 std::vector 包含某个项目。对于Qt,我会这样做:

    QList< int > list;
    list.append( 1 );
    list.append( 2 );
    list.append( 3 );
    
    if ( list.contains( 2 ) )
    {
        // do something
    }
    

    不错,可读性强。但是 没有 contains

    std::vector< int > list;
    list.push_back( 1 );
    list.push_back( 2 );
    list.push_back( 3 );
    
    std::vector< int >::const_iterator result =
        std::find( list.begin(), list.end(), 2 );
    
    if ( result != list.end() )
    {
        // do something
    }
    

    那(对我来说)很难读,而且太冗长了。所以我发现自己在写一个实用函数,它接受一个向量和一个值,然后返回 bool contains() 方法;上面的包装纸 std::find 打电话。然后我可以用类似于Qt示例的方式使用它。

    6 回复  |  直到 15 年前
        1
  •  7
  •   Kirill V. Lyadvinsky    15 年前

    编写实用函数并没有什么错,它将帮助您并使您的代码更干净。其他人也一样。 Boost library 是此类实用函数和类的最大集合。

    更确切地说,C++标准明确建议扩展标准库(7.3.1.2/1):

    该库可以通过C++程序扩展。每一条款(如适用)都描述了此类扩展必须满足的要求。此类扩展通常为以下扩展之一:

    • 模板参数
    • 满足接口约定的容器、迭代器和/或算法
        2
  •  10
  •   bradgonesurfing    15 年前

    基于迭代器的算法。范围

    #include <boost/range/algorithm/find.hpp>
    
    void foo(){
        std::vector<int> list;
        ...
        ...
        boost::find(list, 2) != list.end()
    }
    
        3
  •  3
  •   Justin Ardini    15 年前

    我认为这绝对是个好主意。C++ STL缺少很多Python/C程序员从标准库中得到的期望。如果您可以通过采用2-3行STL方法并使其成为单个函数来提高代码的可读性,请继续!

    int std::string . 令我惊讶的是,使用STL没有简洁的方法来实现这一点。所以,我写了一个 toStr 函数,该函数运行放置 变成一个 stringstream 并返回结果 string .

    编辑:为了澄清,我建议您 boost 在创建自己的解决方案之前。我的示例旨在演示STL的局限性,但有另一种解释,“无论STL缺少什么, 促进 “有。”

        4
  •  1
  •   Gustavo Muenz    15 年前

    与此类似,在我当前的项目中,我们有一个名为:stlutils.h的文件,其中包含一些方法,例如contains()。实施方式:

    template<class Container, class T>
    bool contains(const Container& c, const T& value) {
       return std::find(c.begin(), c.end(), value) != c.end();
    }
    

        5
  •  1
  •   AshleysBrain    15 年前

    其他答案表明,可以编写实用函数来实现这一点,在需要的地方这是一个好主意。但是我想我应该指出一个重要的观点:STL是围绕算法效率而设计的。几乎所有使用STL的操作都有一个标准的big-O效率要求。

    如果 vector 有一个 contains() 成员,调用它肯定是O(n),因为向量是一个简单的连续列表。由于它也很方便,它可能会鼓励程序员定期使用它,甚至在大型数据集上,从而鼓励设计算法性能较差的应用程序。如果是 ,如果查找容器是否包含某个元素很重要,并附加了所有元素都是唯一的保证, std::set 几乎可以肯定是一个更好的选择,使用O(logn)效率查找,甚至O(1)效率查找 std::unordered_set .

    所以我个人的观点是:学习STL提供的所有容器和特性,你会发现虽然它很简洁,但它鼓励一种更有效的编程风格。如果你问这个问题,如果你遗漏了什么,我会说是的-你想更仔细地考虑你使用的容器。我用 set 而不是 这几天经常这样。

        6
  •  1
  •   Ben    15 年前

    我不太喜欢包装纸,但如果它们能帮你,那就去吧。我认为,随着时间的推移,您会发现除了std::vector之外,还需要将实用程序函数用于其他容器。最终您的实用程序函数变得非常通用,您可以直接使用std::find。

    但是你确定你用的是正确的容器吗?set有一个count()方法,它本质上等同于contains()。它是O(log(n)),而不是O(n)。