gTc*_*TcV 8 c++ std min c++-standard-library c++11
阅读这个问题的答案,我惊讶地发现std::min(std::initializer_list<T>)
它的价值取决于它.
如果你std::initializer_list
以其名称隐含的方式使用,即作为某个对象的初始化者,我理解我们不关心复制它的元素,因为它们将被复制以初始化对象.但是,在这种情况下,我们很可能不需要任何副本,因此将参数看作std::initializer_list<const T&>
是可能的更合理.
这种情况的最佳做法是什么?如果你不叫initializer_list
的版本,std::min
如果你关心不进行不必要的副本,或者是有一些其他的办法来避免复制?
没有这样的事情std::initializer_list<const T&>
.初始化程序列表只能按值保存对象.
见[dcl.init.list]/5:
类型的对象
std::initializer_list<E>
是从初始化列表构造的,就好像实现分配了N个元素类型的临时数组const E
,其中N是初始化列表中的元素数.
没有引用数组,因此也不能有引用数组initializer_list
.
在这种情况下,我的建议是编写一个替换,std::min
其中包含转发引用的可变参数模板.这有效(虽然我确信它可以改进):
template<typename T, typename... Args>
T vmin( T arg1, Args&&... args )
{
T *p[] = { &arg1, &args... };
return **std::min_element( begin(p), end(p),
[](T *a, T *b) { return *a < *b; } );
}
Run Code Online (Sandbox Code Playgroud)
看它工作 - 使用min
或mmin
,制作两个额外的副本(for a
和b
).
总结一下评论:
\n\nAnstd::initializer_list
应该是一个轻量级代理,如 cppreference.com上所述。\n因此,初始化程序列表的副本应该非常快,因为不复制底层元素:
C++11\xc2\xa718.9/2
\n\n\n\n\n类型的对象提供对\n
\ninitializer_list<E>
类型的对象数组的访问[注意: \n 一对指针或一个指针加一个长度将是 的明显表示。\n 用于实现 8.5.4 中指定的初始值设定项列表。复制初始值设定项列表不会复制基础元素。\xe2\x80\x94尾注]const E.
initializer_list
initializer_list
不过,使用引用可以归结为使用指针,因此需要额外的间接寻址。
\n\n因此,实际的问题std::min
不是它采用initializer_list
按值,而是如果参数initializer_list
是在运行时计算的,则必须复制参数。[1]\n不幸的是,后来发现 [1] 的基准被破坏了。
auto min_var = std::min({1, 2, 3, 4, 5}); // fast\nauto vec = std::vector<int>{1, 2, 3, 4, 5};\nmin_var = std::min({vec[0], vec[1], vec[2], vec[3], vec[4]}); // slow\n
Run Code Online (Sandbox Code Playgroud)\n\n[1]:N2722页。2
\n 归档时间: |
|
查看次数: |
2897 次 |
最近记录: |