关于C ++中自动变量效率的大小有哪些实际限制?

时间:2012-10-22 20:02:59

标签: c++ memory-management

我有以下变量(简化案例):

std::array<std::array<float, 4>, 4> matrix;

我需要从程序中的函数返回此变量。我可以使用std::unique_ptr或将其作为值(自动与动态内存)返回

由于我平台上浮点数的大小是4个字节,并且有16个位置,因此大小为16 * 4 = 64个字节。

没有自定义分配器等的动态内存除了通常很慢之外还会导致内存碎片,所以我想知道自动内存与动态内存传递数据的实际限制是什么?我应该从什么尺寸开始使用动态内存?问题难以解决吗?

5 个答案:

答案 0 :(得分:2)

如果你担心由于init函数而返回这样的结构的大小,那么我不会(对该语句的警告(如果你不确定,你可以随时测量)。)

所有现代编译器都在进行RVO和NRVO优化。因此,即使您按值返回,也不会生成副本。编译器已经确定结果是去了一个特定的目的地并且已经删除了副本并且正在目的地建立它。

因此,尺寸约束实际上不是问题。

同样在C ++ 11中,引入了移动语义的概念。因此,您不需要按值返回,而是通过移动返回。在大多数std容器中,这只是意味着交换几个指针(不幸的是,这对std :: array没有帮助),但一般情况下它运行良好。

所以对我而言,它可能是一个价值回报。虽然我可以将这个结构包装在一个类中。这样一来,如果真实存在并且它确实花费了很多,我可以在内部更改类以补偿而无需更改代码。

答案 1 :(得分:0)

我不认为你可以通过64字节分配导致任何碎片。根据我在32位环境中使用大型应用程序的经验,大于16 MB的分配可能会因碎片问题而失败。对于导致碎片化的分配,它们应该存在很长时间。对于服务器代码,这超过几天。在64位环境中,不太可能发生碎片化。

按值传递参数意味着创建副本。这可能效率不高。推荐的工作是使用参考。没有众所周知的尺寸限制。

根据我的经验,我会为PC这样的平台推荐以下内容:

  • 变量的大小小于100个字节 - 按值传递;
  • var的大小大于1 KB - 使用引用并避免复制;

值是中间的灰色区域,两个决定都可以。再一次,这些数字没有神奇的含义。只是一些合理的参考。

我建议您考虑使用引用而不是堆分配。

答案 2 :(得分:0)

您是否真的观察到性能下降,然后您追溯到此代码?因为如果这只是一个理论问题,那么我建议你实际上以直观和自然的方式编写事物。

完成这项工作并解决所有问题后,您可以运行该程序,看看您获得的性能是否可以接受;如果它不是那么你可以设置优化实际的瓶颈,而不是想象的瓶颈。

唐纳德克努特说得最好:“我们应该忘记效率低下,大约97%的时间说:过早的优化是所有邪恶的根源。”

答案 3 :(得分:0)

在堆栈上复制64个字节很便宜。它几乎肯定比分配64字节便宜。如果将unique_ptr用于堆上分配的短期变量,则几乎肯定会失去效率。

如果您只是调用您的函数并立即使用返回值,那么它很快。只有当您计划通过一系列矩阵返回函数传播矩阵时,您的效率损失才会显着增加。分配内存和使用unique_ptr的可行性取决于数据重新返回的次数,而不是取决于数据的实际大小。

答案 4 :(得分:-1)

使用动态数组是有点矫枉过正。您不只是分配64个字节来容纳16个浮点数。你为数组分配了4个内存块,每个内存块都有一个堆管理头,每个c ++有一个数组大小,内存中的内存分配器通常会使用大于你要求的块,通常在块边界上对齐。

然后你有保存每个数组的结构的开销。例如。每个std :: array都是一个包含指向对象的指针的类,它至少为8个字节(指针为4个,数组长度为4个)x5。

你没有参考地点。矩阵中的每一行在内存中可能彼此相距很远。如果它们彼此相邻,则会在单个缓存行中读取它们。

只使用以下方式会更好:

float matrix[4][4[

如果您需要面向对象,请将其包装在类中:

class Matrix44 
{
    float matrix[4][4];
}

这样会更有效率。