【问题标题】:C++ allocating memory drawbacks?C ++分配内存的缺点?
【发布时间】:2013-12-30 15:51:59
【问题描述】:

如果我使用以下方式分配了大量 (GB) 内存:

int N = ...;
int * array_ = new int[N];

并且使用数组的一小部分,这种方法有什么缺点,除了明显的事实,我在浪费内存?会影响cpu性能还是让程序不稳定?

这背后的原因是避免使用向量类,因为在密集型应用程序中性能会受到很大影响。

【问题讨论】:

  • vector 不会对性能产生巨大影响
  • 为什么不将您的方法与使用向量进行比较?
  • 嗯,它给出了因为当添加一个新项目时,向量类将所有数组数据复制到一个新数组,然后删除旧数组。基准测试显示命中率至少为 50%,在某些情况下为 100%。
  • 既然您无论如何都无法重新调整原始数组的大小,您的反对意见似乎没有意义 - 为什么不分配一个大向量,这样您就不必重新调整它的大小?
  • @SkyRipper 它给出了因为当添加一个新项时,向量类将所有数组数据复制到一个新数组中,然后删除旧数组——不,它可能不会总是这样做。您也可以使用 vector::reserve() 避免重新分配

标签: c++ ram


【解决方案1】:

取决于操作系统和(可能)程序如何响应内存不足的情况,浪费内存可能会使程序变慢或不稳定。没有保证。

在现代操作系统上,int 的大型但大部分未使用的动态数组应该几乎没有影响。数组中大部分未使用的部分只会被分配虚拟内存空间,它永远不会得到 RAM 或交换的支持。 64 位操作系统(如果你说的是 32GB 的 RAM,你必须使用它)不会缺少虚拟地址空间,直到你用这些东西用完 248 个字节。

这背后的原因是为了避免使用向量类,因为 在激烈的应用程序中表现出色。

创建比您需要的更大的vector<int> 可能会对性能造成很大影响,因为它将被初始化而此数组未初始化。如果这就是你的意思,那么你的代码应该不会比一个巨大的向量引起更多的不稳定性,并且可能更少,因为内存从未被触及。

如果不是这样,那么启用优化的向量应该不会对性能造成太大影响。因此,您可以例如通过使用struct UninitializedInt { int value; UninitializedInt() {} }; 的向量来解决它,以确保无操作默认构造。您可能想添加一个int 构造函数和/或operator int() 以使用户的生活更轻松(防止在整个地方输入.value),尽管这会导致算术运算符模棱两可,所以它不是灌篮。

或者您可以使用reserve() 为向量分配空间,然后根据需要使用resize()push_back()insert()。如果这最终导致您实际上检查边界或修改每次访问的大小,那么您当然只需将一个性能影响替换为另一个。

您的代码应该可以工作。如果您不需要重新实现太多vector 的接口,它可能是消除初始化开销的最简单的方法。当然,您需要确保正确释放它。例如:

std::unique_ptr<int[]> array_(new int[N]);

【讨论】:

    【解决方案2】:

    并且使用数组的一小部分,这种方法有什么缺点,除了明显的事实,我在浪费内存?会影响cpu性能还是让程序不稳定?

    您的代码将难以维护且异常不安全。 (是的,它会的。不,真的。)

    这样做的原因是为了避免使用向量类,因为在密集型应用程序中性能会受到很大影响。

    这在任何可敬的 C++ 实现中都是错误的。 std::vector 的开销为零。编译器比你更擅长优化,可以内联成员函数等等。


    关于您的评论:

    嗯,它给出了因为当添加一个新项目时,向量类将所有数组数据复制到一个新数组,然后删除旧数组。基准测试显示命中率至少为 50%,在某些情况下为 100%。

    std::vector::reserve

    【讨论】:

    • +1 表示“在任何可敬的 C++ 实现中。std::vector 的开销为零。编译器比你更擅长优化”
    • std::vector 的开销为零”在此用例中为假。我的回答包含对大量开销的描述。
    【解决方案3】:

    找到这一点的唯一真正可靠的方法是实际执行并运行性能测试。尝试按照您想到的所有方式进行操作,并根据从这些真实测试中记录的实际数据进行比较和对比。但除此之外,有根据的猜测是您大大高估了std::vector 的性能影响。

    【讨论】:

      【解决方案4】:

      这个问题已经解决了here

      这就是答案:

      使用 std::vector/std::array 总是更好,至少直到你 可以最终证明(通过分析) T* a = new T[100]; 在您的特定情况下,解决方案要快得多。这是 不太可能发生:向量/数组是围绕 a 的极薄层 普通的旧数组。边界检查有一些开销 vector::at,但你可以通过使用 operator[] 来规避它。

      【讨论】:

        【解决方案5】:

        这样做的原因是为了避免使用向量类,因为在密集型应用程序中性能会受到很大影响。

        据我所知,使用向量对性能没有太大影响。除非你能更具体,否则你的整个论点都是无效的(即你应该使用向量)。

        虽然矢量使用不当可能会导致性能开销(问题不在于矢量,而是您的客户端代码)。如果您确实使用矢量,请考虑使用储备。否则,请尝试 std::forward_list 或 std::list (如果您需要添加不一致的元素)。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-07-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-10-25
          • 2010-12-11
          相关资源
          最近更新 更多