【问题标题】:Reducing std::bind template code bloat?减少 std::bind 模板代码膨胀?
【发布时间】:2015-11-04 23:26:02
【问题描述】:

我编写了一个存储std::function<void(void*)> 的对象,它作为参数传递给构造函数。该对象稍后将在将来的某个时间回调此 std::function。这已实施并且效果很好。

在每个使用该对象的类中,它们调用初始化列表中的构造函数,如下所示:

mCallbackObj(std::bind(&MyClass::MyFunc, this, _1))

但是,我发现包含此对象作为成员的每个类都将我的代码空间增加了约 2K。由于可能会在数百个地方使用此对象,并且代码空间选项有限(这是一个嵌入式产品),因此每次使用 2k 命中是不可接受的。

一个有趣的观察是,如果一个类有第二个对象:

mCallbackObj2(std::bind(&MyClass::MyOtherFunc, this, _1))

这只会增加大约 150 字节的代码空间 - 非常可以接受!只有当对象在不同的​​类中使用时,我才会看到 2K 命中。将所有类放在一个 .cpp 文件中并没有帮助 - 每个包含此对象的类仍然有 2k 次命中。

我尝试过使用 extern template class std::function<void(void*)>;,但这对 ROM 大小没有影响。

我正在使用 gcc 4.8。我很想使用std::functionstd::bind,但我即将放弃并切换到类方法指针。它们不会那么干净,但希望 ROM 效率更高。

在我放弃之前,是否有任何其他选项可以帮助减少我的模板代码空间膨胀?

【问题讨论】:

  • 不知道如果你用[this](void* p){ return this->MyFunc(p); }代替bind,情况会不会改变。
  • @IgorTandetnik 可能会稍微好一点,但std::function 仍然会自己生成大量样板文件。
  • std::function 可能是膨胀的原因。 (youtube.com/watch?v=zt7ThwVfap0) 您可以尝试用 lambda 替换绑定,但这不太可能减少二进制大小。
  • 您可以尝试像 fast delegate 这样的轻量级替代方案,使用成员函数指针模板变体:delegate<void(void*)>::from<Foo, &Foo::bar>(&foo);

标签: c++ templates c++11 bind stdbind


【解决方案1】:

我对此进行了深入研究,并在std::function 上观看了@John 的视频。在 video 中,STL 建议使用 lambdas 而不是 std::bind,原因有几个。

我尝试将代码转换为使用 Lambda,这正是上面@Igor Tandetnik 推荐的。明显好很多。

mCallbackObj(std::bind(&MyClass::MyFunc, this, _1))

占用额外的 2,888 字节的代码空间。而是使用

mCallbackObj([this](void *info){MyFunc(info);})

只需要额外的 812 字节!这明显更好,并且对于我的用例来说已经足够好了。对于不熟悉 std::bind 语法的 C++ 程序员来说,lambda 解决方案也更容易阅读。


更新 -

在升级到 GCC 6.0 并调整我们的编译器标志(我们以前并不总是传入 -O2)之后,我重新测试了这个。

Lambda:            216 bytes
std::bind:         221 bytes
function pointer:  228 bytes

现在所有 3 个都更加合理。我们主要使用 lambda,因为一旦开发人员熟悉了语法,它们就最容易阅读。

【讨论】:

    猜你喜欢
    • 2011-03-03
    • 2011-06-27
    • 1970-01-01
    • 2014-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-03
    • 1970-01-01
    相关资源
    最近更新 更多