在SO中有几个问题(like this)关于无法将对象移出初始化列表以及如何导致过多的副本。这个问题不。
我的问题是,鉴于初始化列表基本上是支持浅拷贝的本地有效const引用的容器,为什么它会在创建时导致其(左值)元素的副本?初始化列表中的Rvalues不会被复制,只是被移动,但是lvalues确实被复制了。这是一个显示它的例子:
#include <initializer_list>
#include <iostream>
#include <vector>
struct A
{
A()
{
std::cout << "Creating A" << std::endl;
}
~A()
{
std::cout << "Deleting A" << std::endl;
}
A(const A &other)
{
std::cout << "Copying A" << std::endl;
}
A(A &&other)
{
std::cout << "Moving A" << std::endl;
}
A &operator=(const A &other)
{
std::cout << "Copy-assigning A" << std::endl;
return *this;
}
A &operator=(A &&other)
{
std::cout << "Move-assigning A" << std::endl;
return *this;
}
};
int main(int, char **)
{
A a;
std::cout << "Creating initializer list 1." << std::endl;
std::initializer_list<A> il1 { a };
std::cout << "Created initializer list 1." << std::endl;
std::vector<A> v {A(), A(), A()};
std::cout << "Creating initializer list 2." << std::endl;
std::initializer_list<std::vector<A>> il2 { v };
std::cout << "Created initializer list 2." << std::endl;
return 0;
}
输出(使用GCC 5.4和Clang 3.8):
Creating A
Creating initializer list 1.
Copying A
Created initializer list 1.
Creating A
Creating A
Creating A
Copying A
Copying A
Copying A
Deleting A
Deleting A
Deleting A
Creating initializer list 2.
Copying A
Copying A
Copying A
Created initializer list 2.
Deleting A
Deleting A
Deleting A
Deleting A
Deleting A
Deleting A
Deleting A
Deleting A
相关部分是Creating...
和Created...
之间的部分,可以看出初始化列表生成其参数的副本。查看cppreference,它表示(作为C ++ 14规范的一部分)std::initializer_list<T>
在内部保存一个数组const T[N]
,这将解释副本。我不明白为什么这是必要的。正如评论中所建议的,解决方法是使用指针初始化器列表或std::reference_wrapper
s,但如果内部结构本身是一个指针数组或std::reference_wrapper
s,则不会更好。 ?就像现在一样,看起来好像初始化程序列表与rvalues(或轻型对象)一起使用,但同时它们不允许将对象移出它们。是否存在不将左值复制到内部结构可能有害的情况?或者只是为了避免一个指针取消引用操作?