g++:用闭包类型初始化的 std::function 总是使用堆分配?

2023-11-23

互联网上的一些资源(特别是this one) 表示 std::function 使用小闭包优化,例如如果闭包大小低于一定数量的数据,它不会分配堆(上面的链接指示 gcc 为 16 字节)

所以我开始挖掘 g++ 头文件

看起来是否应用这种优化是由“功能”标头中的这段代码决定的(g ++ 4.6.3)

static void
_M_init_functor(_Any_data& __functor, _Functor&& __f)
{ _M_init_functor(__functor, std::move(__f), _Local_storage()); }

和一些行:

static void
_M_init_functor(_Any_data& __functor, _Functor&& __f, true_type)
{ new (__functor._M_access()) _Functor(std::move(__f)); }

static void
_M_init_functor(_Any_data& __functor, _Functor&& __f, false_type)
{ __functor._M_access<_Functor*>() = new _Functor(std::move(__f)); }
  };

例如,如果 _Local_storage() 为 true_type,则调用placement-new,否则 - 常规 new

本地存储的定义如下:

typedef integral_constant<bool, __stored_locally> _Local_storage;

和 __stored_locally:

static const std::size_t _M_max_size = sizeof(_Nocopy_types);
static const std::size_t _M_max_align = __alignof__(_Nocopy_types);

static const bool __stored_locally =
(__is_location_invariant<_Functor>::value
 && sizeof(_Functor) <= _M_max_size
 && __alignof__(_Functor) <= _M_max_align
 && (_M_max_align % __alignof__(_Functor) == 0));

最后:__is_location_invariant:

template<typename _Tp>
struct __is_location_invariant
: integral_constant<bool, (is_pointer<_Tp>::value
               || is_member_pointer<_Tp>::value)>
{ };

所以。据我所知,闭包类型既不是指针也不是成员指针。为了验证我是否编写了一个小测试程序:

#include <functional>
#include <iostream>

int main(int argc, char* argv[])
{
  std::cout << "max stored locally size: " << sizeof(std::_Nocopy_types) << ", align: " << __alignof__(std::_Nocopy_types) << std::endl;

  auto lambda = [](){};

  typedef decltype(lambda) lambda_t;

  std::cout << "lambda size: " << sizeof(lambda_t) << std::endl;
  std::cout << "lambda align: " << __alignof__(lambda_t) << std::endl;

  std::cout << "stored locally: " << ((std::__is_location_invariant<lambda_t>::value
     && sizeof(lambda_t) <= std::_Function_base::_M_max_size
     && __alignof__(lambda_t) <= std::_Function_base::_M_max_align
     && (std::_Function_base::_M_max_align % __alignof__(lambda_t) == 0)) ? "true" : "false") << std::endl;
}

输出是:

max stored locally size: 16, align: 8
lambda size: 1
lambda align: 1
stored locally: false

所以,我的问题如下:使用 lambda 初始化 std::function 是否总是导致堆分配?或者我错过了什么?


从 GCC 4.8.1 开始,libstdc++ 中的 std::function 仅针对函数和方法的指针进行优化。因此,无论函子(包括 lambda)的大小如何,从中初始化 std::function 都会触发堆分配。不幸的是,也不支持自定义分配器。

Visual C++ 2012 和 LLVM libc++ 确实避免为任何足够小的函子进行分配。

请注意,要在函子中启动此优化,应满足 std::is_nothrot_move_constructible。这是为了支持 noexcept std::function::swap()。幸运的是,如果所有捕获的值都满足此要求,则 lambda 可以满足此要求。

您可以编写一个简单的程序来检查各种编译器上的行为:

#include <functional>
#include <iostream>

// noexpect missing in MSVC11
#ifdef _MSC_VER
# define NOEXCEPT
#else
# define NOEXCEPT noexcept
#endif

struct A
{
    A() { }
    A(const A&) { }
    A(A&& other) NOEXCEPT { std::cout << "A(A&&)\n"; }

    void operator()() const { std::cout << "A()\n"; }

    char data[FUNCTOR_SIZE];
};

int main()
{
    std::function<void ()> f((A()));
    f();

    // prints "A(A&&)" if small functor optimization employed
    auto f2 = std::move(f); 

    return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

g++:用闭包类型初始化的 std::function 总是使用堆分配? 的相关文章

随机推荐

  • clang++ -stdlib=libc++ 导致未定义的引用

    为什么在将 clang 与 libc 一起使用时出现以下链接器错误 clang stdlib libc po cxx lpoppler tmp po QqlXGY o In function main po cxx text 0x33 un
  • 仅对 UITableView 中可用的 CellForRow 显示分隔符

    我正在将 UITableView 与自定义单元格一起使用 它工作正常 但问题是当 UITableView 中只有一两个单元格时 它还为空电池提供了分隔符 是否可以仅为使用自定义单元格加载的单元格显示分隔符 您需要添加一个空页脚视图来隐藏表中
  • 如何从多个 template_folder 加载 Flask 蓝图?

    我学习了如何创建 Flask 蓝图 并且可以为使用 Jinja2 模板的非 Flask 产品创建蓝图并在 Flask 项目中使用它们 我做了这样的事情 blueprint code from flask import Blueprint f
  • 如何在没有 jQuery 的情况下切换元素可见性?

    我正在为 eBay 编写一个拍卖模板 希望 eBay 能够允许 显然他们没有 因为 jquery 有 string replace 等东西 该代码非常基础 document ready function function changeIma
  • Pandas Dataframe选择多个不连续的列/切片

    我有超过 100 列的数据框 我正在尝试选择第 0 32 列和 83 列 看来 1 slice 与下面的代码配合得很好 df new df df columns 0 32 但它不适用于下面的 2 片代码 我该如何解决这个问题 df new
  • 更改 ComboBox 项目的格式

    是否可以在 C 中格式化 ComboBox 项 例如 如何将某个项目设为粗体 更改其文本的颜色等 尽管这篇文章很老 我发现它作为搜索的起点很有用 但最终使用所示的方法得到了更好的结果here由 保罗 这是我用来有条件地使组合框中的项目显示为
  • 如何为 httpclient getasync 方法创建模拟?

    我正在使用 Moq 为单元测试创 建模拟 但是当我必须为 httpclient 的 getasync 方法创建模拟时 我陷入了困境 以前我使用 SendAsync 方法 为此我可以使用以下代码 var mockResponse new Ht
  • 从word文档中提取标题文本

    我正在尝试提取text来自 MS Word 文档 docx 文件 中的 任何级别 标题 目前我正在尝试解决使用python docx 但不幸的是 读完后我仍然无法弄清楚它是否可行 也许我错了 我尝试在网上寻找解决方案 但没有发现任何适合我的
  • 我可以替换或修改 jQuery UI 小部件上的函数吗?如何? (猴子补丁)

    如果我想通过替换其中一个函数来调整 jQuery UI 对象的某些功能 我该怎么做呢 示例 假设我想修改 jQuery 自动完成小部件呈现建议的方式 自动完成对象上有一个方法 如下所示 renderItem function ul item
  • 如何使用 scikit-learn 评估预测的置信度得分

    我写下了一个简单的代码 它采用一个参数 query seq 进一步的方法计算描述符 最后可以使用 LogisticRegression 或该函数提供的任何其他算法 算法作为 0 给定情况为负 进行预测 或 1 给定情况为正 def main
  • 从 NSArray 中检索 NSDictionary,其中字典键的值为 X

    我有一个NSArray with NSDictionaries 数组之一中的字典键之一包含一个值 我想找回NSDictionary具有该值 我的阵列 Array DisplayName level InternalName Number 2
  • 如何在 podfile 中为 Xcode 项目指定多个目标?

    我在 Xcode 4 项目中使用 CocoaPods 我的项目有三个目标 默认目标 一个用于构建精简版本 一个用于构建演示版本 所有目标都使用相同的库 但 CocoaPods 仅将静态库和搜索路径添加到主要目标 我的 podfile 看起来
  • R 中的动态 selectInput 闪亮

    我有 3 个 selectInput 框和一组 4 个选项 可以通过这 3 个框进行选择 我希望 selectInputs 显示的选项在选择其他 selectInputs 时动态更改 不过 我希望所有三个框在任何时间点都可以使用 无 选项
  • Javascript 对象属性是否按顺序分配?

    假设我有一个对象 它根据函数的返回值分配属性 var i 0 var f function return i var foo a f b f c f 是否保证 foo a 为 1 foo b 为 2 foo c 为 3 我知道 JS 不保证
  • Python Paramiko(客户端)多重身份验证

    我正在尝试使用 Paramiko 在 Python 2 7 上 连接到使用多重身份验证 用户名 密码 一次性密码 的主机 这transport auth interactive函数似乎是执行此操作的方法 根据我从文档中理解的内容 但执行从未
  • 对 .net 混淆代码进行逆向工程有多容易?

    市场上有一些程序可以用来混淆您的 net 代码 我的问题是 如果您的代码被 所谓 混淆了 那么别人获取您的 IP 有多容易 混淆 net 代码仅仅是橡皮鸡安全吗 或者说它足以真正保护您的知识产权吗 混淆就像门锁 它让诚实的人保持诚实
  • 插入值语句只能包含 SQL 数据仓库中的常量文字值或变量引用

    考虑这个表 CREATE TABLE t i int j int 我想将一组数据插入到表中SELECT声明 我的查询的简化版本是 INSERT INTO t VALUES SELECT 1 SELECT 2 真正的查询可能要复杂得多 并且各
  • 如何计算Spark结构化流中的滞后差?

    我正在编写 Spark 结构化流程序 我需要创建一个具有滞后差的附加列 为了重现我的问题 我提供了代码片段 这段代码消耗data json文件存储在data folder id 77 type person timestamp 153260
  • 由于覆盖而无法单击按钮?

    这是 HTML li class navs a class Navigation href http youtube com YouTube a li 这是CSS navs after content position absolute t
  • g++:用闭包类型初始化的 std::function 总是使用堆分配?

    互联网上的一些资源 特别是this one 表示 std function 使用小闭包优化 例如如果闭包大小低于一定数量的数据 它不会分配堆 上面的链接指示 gcc 为 16 字节 所以我开始挖掘 g 头文件 看起来是否应用这种优化是由 功