我对复制仿函数和/或初始化器时会发生什么感到困惑。在下面的代码中,我想我会一直复制/移动对象,但不管它是Segfaults。我似乎做错了什么但还没弄明白,我错误的假设是什么。
奇怪的是在 cppreference.com 我找不到initializer_list
的复制或移动构造函数所以我想知道在这些情况下实际发生了什么。
#include <string>
#include <vector>
#include <functional>
#include <iostream>
std::initializer_list<std::function<std::string()>> getInitializer() {
return {
[]() -> std::string {
return "If";
}
};
}
int main() {
std::function<int(std::string)> func;
{
auto init = getInitializer();
func = [init](std::string text) -> int {
std::vector<std::function<std::string()>> vec(init);
for( auto& el : vec ) {
std::cout << el();
}
std::cout << text << std::endl;
return 5;
};
}
return func(" you see this - the world is all right!");
}
答案 0 :(得分:7)
我对initializer_list
没有太多经验,但标准似乎暗示initializer_list
的实现就好像它是一对数组的指针。 getInitializer
的列表具有自动生存期,支持它的数组也是如此。最终返回一对指向不再存在的数组的指针。
标准的相关部分是8.5.4 [decl.init.list]第5和第6项:
5.-类型
std::initializer_list<E>
的对象是从初始化列表构造的,就好像实现分配了一个类型为E
的 N 元素数组,其中 N 是初始化列表中的元素数。使用初始化列表的相应元素对该数组的每个元素进行复制初始化,并构造std::initializer_list<E>
对象以引用该数组。如果需要缩小转换来初始化任何元素,则程序格式不正确。6.-数组的生命周期与
initializer_list
对象的生命周期相同。
因此,对于您的特定情况,实现将大致相当于:
std::initializer_list<std::function<std::string()>> getInitializer() {
std::function<std::string()> __a[1] = {
[]() -> std::string {
return "If";
}
};
return std::initializer_list<std::function<std::string()>>(__a, __a+1);
}