仿函数和initializer_list的副本

abe*_*ier 4 c++ gcc functor initializer-list c++11

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

K-b*_*llo 7

我对initializer_lists 没有太多的经验,但是标准似乎暗示了一个实现,initializer_list就好像它是一对数组的指针.该列表getInitializer具有自动生命周期,支持它的数组也是如此.您最终返回一对指向不再存在的数组的指针.

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

5.-类型的对象std::initializer_list<E>是从初始化列表构造的,就好像实现分配了N个元素类型的数组E,其中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);
}
Run Code Online (Sandbox Code Playgroud)