c ++

时间:2019-02-04 18:59:19

标签: c++ c++11 stl inline overhead

我喜欢在列表上编写对功能的检查。为此,我通常编写如下函数:

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-应用于内联函数?而使用{}括号创建时,其中哪一个具有最低甚至为零的开销

好的,然后更新:我抓住了朋友授权的IDA Pro,并检查了一些选项。

  • std::initializer_list:该函数甚至没有内联,并且在那里 是创建列表和复制指针的开销。
  • std::vector:该函数可以内联,但是有一个 创建向量并在那里复制指针的开销。
  • std::array:由于模板专业化,外观不佳, 并且该函数未内联。因此,多次调用会创建 许多类似的代码块。但是,阵列没有开销 创建,并将所有指针作为函数参数传递, x86_64注册调用约定很快。

问题仍然存在,是否有一个绝对零成本的集装箱

4 个答案:

答案 0 :(得分: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中利用可变参数模板,但是您要么需要使用递归,要么构建自己的数组,这实际上并不会给您带来任何额外的复杂性。

答案 1 :(得分:0)

好的,由于之前的回答,我弄清楚了。如果人们说“没有更好的容器存在”,那么std :: array是最好的。当使用优化级别-O2进行编译时,std::array既不复制参数也不调用函数,而std :: initializer_list则不复制参数。使用-O0进行编译时,一切如我在问题本身中所述。

所以我的解决方案:使用std::array并应对参数数量指定<N>

答案 2 :(得分:0)

如果您真的很担心使用容器,则可以编写C:\Users\WILL>npm install -g dnr-editor npm WARN deprecated bcrypt@1.0.3: bcrypt < v2.0.0 is susceptible to bcrypt wrap-around bug. Upgrade to bcrypt >= v2.0.0 for improved support for newer bcrypt hashes npm WARN deprecated mongodb@2.1.21: Please upgrade to 2.2.19 or higher npm WARN deprecated node-uuid@1.4.8: Use uuid module instead npm WARN deprecated mailparser@0.6.2: Mailparser versions older than v2.3.0 are deprecated npm WARN deprecated nodemailer@1.11.0: All versions below 4.0.1 of Nodemailer are deprecated. See https://nodemailer.com/status/ npm WARN deprecated mimelib@0.3.1: This project is unmaintained npm WARN deprecated mailcomposer@2.1.0: This project is unmaintained npm WARN deprecated buildmail@2.0.0: This project is unmaintained C:\Users\WILL\AppData\Roaming\npm\dnr-editor -> C:\Users\WILL\AppData\Roaming\npm\node_modules\dnr-editor\red.js 重载,例如为N

N = 5

答案 3 :(得分:-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。不需要容器。