4

我对复制仿函数和/或初始化程序时会发生什么感到有些困惑。在下面的代码中,我认为我会一直复制/移动对象,但不管它是 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!");
}
4

1 回答 1

7

我对 s 没有太多经验initializer_list,但标准似乎建议 an 的实现initializer_list就好像它是一对指向数组的指针。at 的列表getInitializer具有自动生命周期,支持它的数组也是如此。您最终会返回一对指向不再存在的数组的指针。

标准的相关部分是 8.5.4 [decl.init.list] 第 5 和 6 项:

5.-std::initializer_list<E>从初始化列表构造一个类型的对象,就好像实现分配了一个由 N 个类型元素组成的数组其中EN初始化列表中的元素数。该数组的每个元素都使用初始值设定项列表的相应元素进行复制初始化,并且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);
}
于 2012-06-24T01:41:43.150 回答