【问题标题】:How to decide on stack vs heap vs boost::pool allocation in a case like this?在这种情况下,如何决定堆栈、堆和 boost::pool 分配?
【发布时间】:2011-06-07 12:57:02
【问题描述】:

我有一个类使用 boost::variant 来存储双精度或字符串,如下所示:

class value
{
  boost::variant<double, std::string> val;
};

对于我正在玩的玩具解释器来说,它应该是一个不可变的值类型。 起初,通过 const 引用传递它并按值返回似乎是一个好主意,并始终将它分配在堆栈上,因为我希望它被视为原语。但是,后来我看到它的大小是 40 字节(主要是由于 std::string 的 sizeof),我有点担心。我知道我不应该在堆栈上分配大块内存,但是多大才算太大?

另外,每次返回时复制 40 个字节,特别是因为该值是不可变的,甚至不需要复制,这似乎有点浪费。

常规堆分配选项似乎不太有吸引力,因为我每秒可以进行数千次这样的分配/解除分配。

我想出的最后一个选择是在需要时使用 boost::pool 来分配这些对象,并使用 boost::shared_ptr 来管理它们的生命周期。然而,因为解释器负责内存分配(内存分配的类型将是作为模板参数传递给解释器的策略),这意味着值类必须知道解释器,这会使事情稍微复杂化.

所以这些是问题:

  • 在这种情况下我应该怎么做?为什么?
  • “太大”在堆栈上分配有多大?我确信这取决于分配的频率以及必须复制的频率。

谢谢。

【问题讨论】:

  • sizeof(std::string) 是 8,sizeof(value) 在 linux/x86_64 上是 16。这 40 个字节来自哪里?
  • sizeof(std::string) is 32, sizeof(value) is 40 on Windows 7, 64bit, Visual Studio 2010 :|
  • @Luther 微软实现中 std::string 的小字符串优化解释了 32 字节大小。

标签: c++ boost boost-variant boost-pool


【解决方案1】:
  • 在这种情况下我应该怎么做?为什么?

与往常一样,编写程序,使其最容易理解。 如果稍后分析发现这确实是一个问题,您可以随时将value::val 转换为一些动态分配的对象。 (当然,这假定 val 被抽象得足够好,不会影响到任何类的客户。)

  • “太大”在堆栈上分配有多大?我确信这取决于分配的频率以及必须复制的频率。

这还取决于您使用的平台。我们是在谈论运行烤面包机的 8 位嵌入式芯片还是 64 位工作站?
IMO 最终归结为:如果由于它的大小而产生问题,那就太大了。

【讨论】:

  • 如果有需要,也可以使用享元模式。
【解决方案2】:

如果你真的需要优化这个,我建议不要在 Windows 上使用std::string

对于不可变字符串,可以在shared_ptr 之上轻松实现类似写时复制的实现(基本上,字符串的所有副本共享相同的内部缓冲区)。

从那时起,您在 ConstString 类中只需要一个指针,您不必担心通过副本传递。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-06-26
    • 2021-05-18
    • 2012-04-23
    • 2017-08-12
    • 2016-08-30
    • 1970-01-01
    • 2014-10-04
    • 2012-11-05
    相关资源
    最近更新 更多