c ++中内联函数的零成本列表

Mor*_*orJ 6 c++ stl inline overhead c++11

我喜欢在列表上编写函数检查.为此我通常写一个这样的函数:

inline bool good_strings(const std::vector<const char *> & items)
{
    for (i in items) {
        if (not is_good(i)) return false;
    }
    return true;
}
Run Code Online (Sandbox Code Playgroud)

然后我可以写得像if (all_good({"a", "b", "c", "d", "e"})) {...},它看起来非常好.当您对几件物品的检查变得更大时,这很好用:

if (is_good("a") and is_good("b") and /* that's too much, man */ is_good("c")) {...}
Run Code Online (Sandbox Code Playgroud)

但我关心的是我使用的容器的开销,也很难选择一个:std::vector,std::list,QList,QStringList或者甚至std::arraystd::initializer_list- 应该使用内联函数?在使用括号创建时,这些中的哪一个具有最小甚至零开销{}

好的,并且更新:我抓住了我的朋友许可的IDA Pro并检查了一些选项.

  • std::initializer_list:该函数甚至没有内联,并且存在创建列表和复制指针的开销.
  • std::vector:函数内联,但是,创建向量和复制指针存在开销.
  • std::array:由于模板特化而不是很好看,而且函数没有内联.因此,多次调用会创建许多类似的代码块.但是,没有数组创建的开销,并且所有指针都作为函数参数传递,这对于x86_64寄存器调用约定来说很快.

问题仍然存在,是否有一个绝对零成本的容器

Nat*_*ica 12

没有任何容器将成为零开销. std::array或者std::initializer_list会给你最少的费用. std::array需要它在编译时指定的类型和大小,所以它std::initializer_list在这种情况下比用户友好一点.因此,使用a std::initializer_list<const char*>将是您可以使用的最小且最容易使用的"容器".它将花费编译器生成的指针数组的大小,并且可能会花费更多,并且不需要任何动态内存分配.


如果你可以使用C++ 17你甚至不需要容器.利用可变参数模板折叠表达式, 您可以将所有参数作为单独的参数传递给函数,并将相同的操作应用于所有参数.

template<typename... Args>
bool good_strings(Args&&... args)
{
    return (is_good(args) && ...);
}
Run Code Online (Sandbox Code Playgroud)

将转向

all_good("a", "b", "c", "d", "e")
Run Code Online (Sandbox Code Playgroud)

return is_good("a") && is_good("b") && ... && is_good("e");
Run Code Online (Sandbox Code Playgroud)

它利用短路,因此一旦第一次调用is_good返回false ,它就会停止评估.

您可以利用在C++ 11的可变参数模板,但你要么需要使用递归,或建立自己的阵列,这真的没有得到你额外的复杂性,你会有什么.

  • @MorJ这实际上需要C++ 17(用于fold表达式).您只限于哪个版本的C++? (2认同)