我喜欢在列表上编写对功能的检查。为此,我通常编写如下函数:
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::vector
,std::list
,QList
,QStringList
甚至std::array
或std::initializer_list
-应用于内联函数?而使用{}
括号创建时,其中哪一个具有最低甚至为零的开销?
好的,然后更新:我抓住了朋友授权的IDA Pro,并检查了一些选项。
std::initializer_list
:该函数甚至没有内联,并且在那里
是创建列表和复制指针的开销。std::vector
:该函数可以内联,但是有一个
创建向量并在那里复制指针的开销。std::array
:由于模板专业化,外观不佳,
并且该函数未内联。因此,多次调用会创建
许多类似的代码块。但是,阵列没有开销
创建,并将所有指针作为函数参数传递,
x86_64
注册调用约定很快。问题仍然存在,是否有一个绝对零成本的集装箱?
答案 0 :(得分:12)
所有容器的开销都不会为零。 std::array
或std::initializer_list
的费用最少。 std::array
需要在编译时指定其类型和大小,因此在这种情况下,它比std::initializer_list
的用户友好度要低一些。因此,使用std::initializer_list<const char*>
将是最小且最容易使用的“容器”。这将花费编译器生成的指针数组的大小,甚至可能更多,并且不需要任何动态内存分配。
如果可以使用C ++ 17,则甚至不需要容器。使用variadic template和fold 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
。不需要容器。