fre*_*low 88 c++ templates initializer-list move-semantics c++11
我允许将元素移出std::initializer_list<T>
?
#include <initializer_list>
#include <utility>
template<typename T>
void foo(std::initializer_list<T> list)
{
for (auto it = list.begin(); it != list.end(); ++it)
{
bar(std::move(*it)); // kosher?
}
}
Run Code Online (Sandbox Code Playgroud)
由于std::intializer_list<T>
需要特殊的编译器注意并且没有像C++标准库的普通容器那样的值语义,所以我宁愿安全而不是抱歉并且问.
Pot*_*ter 82
不,这不会按预期工作; 你仍然会得到副本.我对此感到非常惊讶,因为我认为initializer_list
存在一系列的临时工,直到他们为止move
.
begin
并且end
对于initializer_list
return const T *
,所以move
代码中的结果是T const &&
- 一个不可变的右值引用.这样的表达无法有意义地被移除.它将绑定到类型的函数参数,T const &
因为rvalues绑定到const左值引用,您仍将看到复制语义.
原因可能是编译器可以选择initializer_list
使用静态初始化的常量,但是看起来它的类型initializer_list
或const initializer_list
编译器可以自行决定是否更清晰,因此用户不知道是期望const
还是可变的结果来自begin
和end
.但这只是我的直觉,可能有一个很好的理由我错了.
更新:我已经编写了ISO提议,以initializer_list
支持仅移动类型.它只是初稿,并没有在任何地方实现,但你可以看到它来更多地分析问题.
Nic*_*las 17
bar(std::move(*it)); // kosher?
Run Code Online (Sandbox Code Playgroud)
不是你想要的方式.您无法移动const
对象.并且std::initializer_list
只提供const
对其元素的访问.所以类型it
是const T *
.
您的通话尝试std::move(*it)
只会产生一个l值.IE:副本.
std::initializer_list
引用静态内存.这就是班级的用途.你无法从静态内存中移动,因为移动意味着要改变它.您只能从中复制.