代码之家  ›  专栏  ›  技术社区  ›  Benoît Dubreuil

单个运算符和数组全局运算符是否执行相同的操作?[重复]

c++
  •  1
  • Benoît Dubreuil  · 技术社区  · 7 年前

    正如我们所知,C++标准定义了两种形式的全局分配函数:

    void* operator new(size_t);
    void* operator new[](size_t);
    

    此外,草案的C++标准(18.61.2 N37 97)说:

    227)这不是运营商的直接责任 new或operator delete以记录重复 数组的计数或元素大小。这些操作都是执行的 数组中的其他位置新建和删除表达式。新阵列 然而,表达式可能会将大小参数增加到运算符 获取存储补充信息的空间。

    让我困惑的是:

    如果我们移除 void* operator new[](size_t); 从标准开始,只需使用 void* operator new(size_t) 相反定义冗余全局分配函数的基本原理是什么?

    0 回复  |  直到 12 年前
        1
  •  12
  •   Potatoswatter    12 年前

    我想 ::operator new[] 对于那些“大而少”的数组可能由与“小而多”的对象不同的分配器分配的相当专业的系统来说,这可能很有用。然而,它现在是一个遗迹。

    operator new 可以合理地预期将在返回的确切地址构造对象,但是 operator new[] 不能分配块的第一个字节可能用于大小“cookie”,数组可能被稀疏地初始化,等等。这种区别对成员来说更有意义 新接线员 ,这可能是针对其特定类别的。

    无论如何, ::新操作员[] 不是很重要,因为 std::vector (via) std::allocator ),这是目前最流行的获取动态数组的方法,但忽略了它。

    在现代C++中,自定义分配器通常比定制更好。 新接线员 事实上 new 应该完全避免使用表达式,而使用容器(或智能指针等)类,这样可以提供更多的异常安全性。

        2
  •  6
  •   Tony Delroy    12 年前

    ::operator new[] 及~ delete[] 促进内存使用调试,成为审核分配和解除分配操作的中心点;然后,您可以确保数组形式同时用于这两种情况,或者两者都不用于。

    如果非常不寻常/粗糙的调整使用,也有很多合理的用途:

    • 从一个单独的池中分配阵列,可能是因为这大大提高了动态分配的单个小对象的平均缓存命中率,

    • 不同的内存访问提示(ala) madvise )对于阵列/非阵列数据

    所有这些都有点奇怪,超出了99.999%程序员的日常担忧,但为什么要阻止它成为可能呢?

        3
  •  6
  •   david.pfx    12 年前

    该标准(n3936)明确规定,这两个运营商服务于不同但相关的目的。

    operator new 调用函数 void* operator new(std::size_t) .第一个参数必须与运算符的参数相同。它返回一个适当对齐的存储块,该存储块可能比所需的大一些。

    operator new[] 调用函数 void* operator new[](std::size_t) 。第一个参数可能大于提供给运算符的参数,以便在需要时为数组索引提供额外的存储空间。两者的默认实现都是简单地调用malloc()。

    目的 新操作员[] 是为了支持专门的数组索引(如果可用)。它与内存池或其他任何东西无关。在使用此功能的一致性实现中,该实现将在额外的空间中设置专门的表,编译器将生成指令代码或对使用这些表的库支持例程的调用。使用数组的C++代码和不使用新的[]将在这些平台上失败。

    我个人不知道有任何这样的实现,但它类似于支持某些大型机(CDC、IBM等)所需的功能,这些大型机的体系结构与我们所知道和喜爱的英特尔或RISC芯片截然不同。

    在我看来,公认的答案是不正确的。


    为完整起见,本标准(n3936主要在S5.3.4中)包含以下内容。

    1. 分配“数组对象”或“非数组对象”之间的区别
    2. 对“数组分配开销”的引用,暗示可能需要额外的存储,并且可能(以某种方式)用于重复计数或元素大小。

    没有提到内存池,也没有暗示这可能是一个考虑因素。

        4
  •  2
  •   yzt    12 年前

    我确信有一些适当的用例需要单独的 new[] new ,但我还没有遇到一个在这种分离中唯一可能的方法。

    然而,我是这样看的:因为用户调用了不同版本的operator C++标准会是故意的和故意的。 丢失信息 如果他们只定义了一个 operator new 而且两者都有 新的[] 往前走。这里(字面上)有一点信息 可以 有益于 某人 ,我认为委员会里的人不可能出于良心把它扔掉!

    此外,必须实施额外的 新的[] 对我们其他人来说是一个非常非常小的不便,如果有的话,因此,在保留一点信息与在我们的一小部分程序中实现一个简单函数之间进行权衡是成功的。

        5
  •  -1
  •   Andy Dent    12 年前

    C++程序设计语言:特别版 第423页说

    _那个 operator new() operator delete() 函数允许用户接管单个对象的分配和解除分配; operator new[]() operator delete[]() 为数组的分配和释放提供完全相同的角色。

    感谢Tony D纠正了我对这种细微差别的误解。

    哇,我经常不知道C++中的某些东西,我肯定是——我一定花太多时间在Objto-C了!

    原始错误答案

    很简单——新的[]表格 invokes the constructor 在经典C数组的每个元素上。

    因此,它首先为所有对象分配空间,然后为每个插槽迭代调用构造函数。