在C内联函数零成本清单++

问题描述 投票:6回答:4

我喜欢写检查了列表的功能。为此,我通常会写这样的功能:

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

然后,我可以写这样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")) {...}

但我关心的是我使用的容器的开销,也很难选择一个:std::vectorstd::listQListQStringList或者甚至std::arraystd::initializer_list - 这应该使用内联函数?而这些A的使用{}括号创建时有最低甚至是零开销?

好吧,和更新:我抓住了我的朋友行货IDA Pro和检查一些选项。

  • std::initializer_list:该功能甚至不在线,并有一定的开销用于创建列表和复制指针。
  • std::vector:功能并直列,然而,存在用于创建矢量和复制指针有一个开销。
  • std::array:不是好看,因为模板的专业化,以及功能不在线。因此调用了很多次,创造了许多代码块类似。然而,没有任何开销阵列创建,所有指针作为函数的参数,这是快x86_64寄存器调用约定通过。

现在的问题是,是否有一个绝对零成本的容器?

c++ c++11 stl inline overhead
4个回答
12
投票

容器没有将是零开销。 std::arraystd::initializer_list会给你的成本最少的,但。 std::array需要它在编译时指定的类型和大小,因此它是一个有点不太人性化,然后在这种情况下std::initializer_list。因此,使用std::initializer_list<const char*>将是最小的和最容易使用的“容器”,你可以使用。这将花费指针数组的大小编译器生成和更可能一点,它不需要任何动态存储器分配。


如果你可以使用C ++ 17你甚至都不需要一个容器。利用variadic templatefold expression你可以传递给函数作为单独的参数的所有参数和相同的操作适用于所有的参数。

template<typename... Args>
bool good_strings(Args&&... args)
{
    return (is_good(args) && ...);
}

将转向

all_good("a", "b", "c", "d", "e")

return is_good("a") && is_good("b") && ... && is_good("e");

它利用短路所以它会很快停止评估作为第一个呼叫is_good返回false。

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


0
投票

如果你真的关心使用的容器,你可以只写N过载,例如对于N = 5

inline bool good_string(const char* a)
{
    return true;
}
inline bool good_strings(const char* a, const char* b)
{
    return good_string(a) && good_string(b);
}
inline bool good_strings(const char* a, const char* b, const char* c)
{
    return good_strings(a, b) && good_string(c);
}
inline bool good_strings(const char* a, const char* b, const char* c, const char* d)
{
    return good_strings(a, b, c) && good_string(d);
}
inline bool good_strings(const char* a, const char* b, const char* c, const char* d, const char* e)
{
    return good_strings(a ,b, c, d) && good_string(e);
}

0
投票

好吧,得益于以前的答案的想法,我理解了它。如果有人说什么“没有更好的集装箱存在”,那么标准::数组是最好的。当与优化级别-O2编译,std::array既没有参数复制,也不是函数调用,而性病:: initializer_list有参数复制。当-O0编译这一切,因为我在这个问题本身说明。

所以我的解决办法:用std::array,并指定为<N>参数的数目应对。


-2
投票

如果这样,你模板功能:

bool is_good(const std::string &) { return true; )
template<typename Container>
inline bool good_strings(const Container & items)
{
    for (auto const &i : items){
        if (not is_good(i)) return false;
    }
    return true;
}

然后调用good_strings(std::initializer_list<std::string>{"a", "b", "c", "d", "e"})将通过初始化列表来all_good。无容器所需。

© www.soinside.com 2019 - 2024. All rights reserved.