dte*_*ech 30 c++ performance variadic-functions initializer-list c++11
我一直想知道可变参数比初始化列表有什么优点.两者都提供相同的能力 - 将无限数量的参数传递给函数.
我个人认为初始化列表更优雅一些.语法不那么尴尬.
此外,随着参数数量的增加,初始化程序列表似乎具有明显更好的性能.
所以除了在C中使用可变参数的可能性之外我还缺少什么?
And*_*owl 50
如果你使用变量参数表示省略号(如void foo(...)),那么变量模板或者初始化列表或多或少都会使这些变量过时- 在使用SFINAE实现时(例如),省略号仍然可能存在一些用例类型特征,或C兼容性,但我会在这里讨论普通用例.
事实上,变量模板允许参数包的不同类型(实际上,任何类型),而初始化列表的值必须可转换为初始化列表的基础类型(并且不允许缩小转换):
#include <utility>
template<typename... Ts>
void foo(Ts...) { }
template<typename T>
void bar(std::initializer_list<T>) { }
int main()
{
foo("Hello World!", 3.14, 42); // OK
bar({"Hello World!", 3.14, 42}); // ERROR! Cannot deduce T
}
Run Code Online (Sandbox Code Playgroud)
因此,当需要类型推导时,初始化程序列表不常使用,除非参数的类型确实是同质的.另一方面,可变参数模板提供椭圆可变参数列表的类型安全版本.
此外,调用带有初始化列表的函数需要将参数括在一对大括号中,而采用可变参数包的函数则不是这种情况.
最后(好吧,还有其他差异,但这些与您的问题更相关),初始化列表中的值是const对象.根据C++ 11标准的第18.9/1段:
类型的对象
initializer_list<E>提供对类型对象数组的访问const E.[...]复制初始化列表不会复制基础元素.[...]
这意味着尽管可以将不可复制的类型移动到初始化列表中,但它们不能移出它.此限制可能符合或不符合程序的要求,但通常会使初始化列表成为保留不可复制类型的限制选择.
更一般地说,无论如何,当使用一个对象作为初始化列表的元素时,我们将复制它(如果它是一个左值)或远离它(如果它是一个右值):
#include <utility>
#include <iostream>
struct X
{
X() { }
X(X const &x) { std::cout << "X(const&)" << std::endl; }
X(X&&) { std::cout << "X(X&&)" << std::endl; }
};
void foo(std::initializer_list<X> const& l) { }
int main()
{
X x, y, z, w;
foo({x, y, z, std::move(w)}); // Will print "X(X const&)" three times
// and "X(X&&)" once
}
Run Code Online (Sandbox Code Playgroud)
换句话说,初始化程序列表不能用于通过引用(*)传递参数,更不用说执行完美转发:
template<typename... Ts>
void bar(Ts&&... args)
{
std::cout << "bar(Ts&&...)" << std::endl;
// Possibly do perfect forwarding here and pass the
// arguments to another function...
}
int main()
{
X x, y, z, w;
bar(x, y, z, std::move(w)); // Will only print "bar(Ts&&...)"
}
Run Code Online (Sandbox Code Playgroud)
(*)但必须注意,初始化列表(与C++标准库的所有其他容器不同)确实具有引用语义,因此尽管在将元素插入初始化列表时执行元素的复制/移动,但复制初始化列表本身不会导致所包含对象的任何复制/移动(如上面引用的标准段落中所述):
int main()
{
X x, y, z, w;
auto l1 = {x, y, z, std::move(w)}; // Will print "X(X const&)" three times
// and "X(X&&)" once
auto l2 = l1; // Will print nothing
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
11955 次 |
| 最近记录: |