【问题标题】:Generic lambdas and binary size / code bloat通用 lambdas 和二进制大小/代码膨胀
【发布时间】:2018-09-12 23:15:14
【问题描述】:

当我们比较这段代码时,生成的二进制文件有什么区别:

struct S {
    template<typename... Args>
    void operator()(Args... args) { /* ... */ }
};

// And then inside some block:
S s;
s(42);
s(3.14, "Hi!");
s("Hi!", 3.14);

...到此代码:

const auto l = [](auto... args) { /* ... */ };

// And then inside some block:
l(42);
l(3.14, "Hi!");
l("Hi!", 3.14);

据我了解,struct 代码为operator() 创建了 3 个模板实例化,所有这些实例化都在二进制文件中显示为符号。拉姆达呢?编译器创建一个类似于s 的对象。但是如果它是一个未命名的类类型,它会在二进制文件中创建符号吗?

动机:我使用了一个模板繁重的库,我必须在其中启用/bigobj。我想避免这种情况,我想知道 lambdas 是否可以帮助防止模板代码膨胀。这是在标准中定义的,还是依赖于编译器实现?

【问题讨论】:

  • 在这种情况下,内联实际上会有所帮助,删除 lambda 的符号。
  • 尝试将结构放在一个未命名的命名空间中。
  • 查看您的编译器输出并找出您的实际问题。模板等是语法糖。 “代码膨胀”现在已经不像 20 年前那么重要了,存储成本也远低于开发人员的时间。你在这里的实际目标是什么?你的例子做同样的事情。如果它编译,那是因为编译器将为auto 生成不同的版本,就像它为模板生成的一样。 auto 不提供动态类型。它仍然是一种静态类型的语言,不同的类型需要不同的版本。模板,其他编译器魔法 - 没关系。
  • 我会假设后一个示例甚至无法编译,因为参数在不同的调用中具有不同的类型?
  • @crazypeter 这是通用 lambda 的一个特性。

标签: c++ c++11 templates lambda generic-lambda


【解决方案1】:

我认为,很遗憾,lambda 无法帮助您解决代码膨胀的问题。对于你的例子,像 struct S 一样,编译器也会为 lambda 创建三个不同的 operator ()。

为了证明我的观点,我在Linux上用g++ 8.1.0编译了如下程序。

int main()
{
    const auto l = [](auto... args) { /* ... */ };
    l(42);
    l(3.14, "Hi!");
    l("Hi!", 3.14);
}

然后使用nm命令查看二进制文件,结果如下:

不难看出,最后三行是三个运算符()的符号。所以,在这种情况下,lambda 和 struct S 并没有根本的不同。

【讨论】:

  • 谢谢!很高兴知道。
猜你喜欢
  • 2015-02-08
  • 1970-01-01
  • 1970-01-01
  • 2015-07-21
  • 2020-02-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多