仿函数和initializer_list的副本

时间:2012-06-24 01:12:25

标签: c++ gcc c++11 functor initializer-list

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

1 个答案:

答案 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);
}