【问题标题】:new A[0] -- Legal, but of what use? What does it actually do?new A[0] -- 合法,但有什么用?它实际上是做什么的?
【发布时间】:2012-06-19 22:01:22
【问题描述】:

根据 C++03 标准(5.3.4/7):

当直接新声明符中表达式的值为零时, 调用分配函数来分配一个没有 元素。

根据我的阅读,这意味着该代码是合法的并且具有特定的效果:

#include <iostream>
#include <string>
using namespace std;

class A
{
public:
    A() : a_(++aa_) {};
    int a_;
    static int aa_;
};
int A::aa_ = 0;

int main()
{
    A* a = new A[0];
    // cout << "A" << a->a_ << endl; // <-- this would be undefined behavior
}

当我在调试器下运行这段代码时,我看到A 的构造函数从未被调用过。 new 不会抛出,而是返回一个非空的、明显有效的指针。但是,a-&gt;a_ 处的值是未初始化的内存。

问题:

  1. 在上面的代码中,a究竟指向什么?
  2. “分配一个没有元素的数组”是什么意思?
  3. 分配一个元素为零的数组有什么实际用途?

【问题讨论】:

  • a 指向一个零元素数组。这么难理解吗?
  • @HotLicks:是的,有点。让我的头爆炸了。 :)
  • 我这里最大的问题是#3。分配一个零元素数组有什么实际用途?
  • @JohnDibling:这意味着用户代码不需要检查零。
  • #3的好处是接口是统一的,所以如果你有一个对象可以有一个“最多N”个元素的固定数组组件,你可以处理,无需特殊情况, N==0 案例。

标签: c++ new-operator


【解决方案1】:

归结为:new whatever[0] 会返回一个有效地址,不同于任何其他当前分配的对象,但您不能取消引用。

它的典型用途是用于分配不同大小数组的代码,因此有时您可能有一个包含正数元素的数组,但有时是一个包含零元素的数组。即使您不能取消引用它,使用“正常”(有效)指针而不是(例如)空指针仍然可以简化相当多的代码。

仅举一个例子,考虑存储数组开始地址的典型情况,以及超出数组末尾的地址(并且具有从一个到另一个遍历的循环)。使用空指针,您不能进行这样的算术运算,因此任何处理过尾指针的事情都需要对空指针进行特殊的大小写。在您无法取消引用的有效非空指针的情况下,您仍然可以在没有任何特殊情况的情况下形成起始地址和结束地址。您编写的普通循环在数组为空时执行零次迭代,而不是只为非空指针执行循环的特殊代码。

【讨论】:

  • 显然,“指向元素过去的指针”是一种未定义行为。见stackoverflow.com/questions/10473573/…。不过仅供参考。
  • @quetzalcoatl:那是一个指针 两个 超过末尾。零到末尾是有效的指针。 form 一个指针在末尾之后是有效的,并且它可以对数组中的指针进行有效的比较(您只是不能取消引用它)。然而,超过这一点的指针甚至不能合法地形成
【解决方案2】:

您的a (有效)指向零个连续元素,并且已经构造了零个元素。表达式a-&gt;a_a[0].a_ 相同,超出范围,因此行为未定义。

此外,“a-&gt;a_ 处的值是未初始化的内存”这句话似乎没有意义:一个值就是一个值,而内存就是内存——一个值不能成为内存.由于我们已经确定您永远不能取消引用a,因此要求a 指向的变量的任何类型的值都是没有意义的:a 只是没有指向任何有用的地方。

delete[] a; 释放分配的内存并销毁所有零对象仍然是完全有效的(并且预期?!)。

(注意C的malloc函数也可以用参数0调用,但是除了free它之外,不能保证它的返回值。在C++中,::operator new[]实际上是需要返回的distinctnon-null 每次值(受重用已传递给 ::operator delete[] 的值的限制)。

【讨论】:

  • +1:当然,你所说的一切都很有道理。对分配零元素数组的实际用途有何评论?
  • @JohnDibling:这意味着您不需要在某些算法中添加额外的检查。您可以通用地编写,而不必担心是否有您没有考虑到的奇怪的边缘案例。请注意,malloc 具有相似的语义。
  • 好的,这似乎是一个合理的解释。不处理边缘案件的想法明确地激怒了我,但标准从未说过我必须这样做。 :)
【解决方案3】:

在上面的代码中,a实际指向什么?

指向零元素数组。

“分配一个没有元素的数组”是什么意思?

这意味着我们得到了一个有效的数组,但大小为零。我们无法访问其中的值,因为没有,但是我们现在每个零大小的数组都指向不同的位置,我们甚至可以创建一个迭代器到过去的&amp;a[0]。所以我们可以像使用其他数组一样使用它。

分配一个元素为零的数组有什么实际用途?

它只是让您不必在每次调用new 时检查n = 0。请注意,大小为零的静态数组是非法的,因为静态数组具有来自常量表达式的静态大小。此外,允许您使用一对迭代器调用任何标准或自定义算法。

【讨论】:

    猜你喜欢
    • 2011-09-04
    • 1970-01-01
    • 1970-01-01
    • 2019-10-27
    • 2012-01-08
    • 1970-01-01
    • 2011-03-11
    • 2010-11-26
    • 2015-06-23
    相关资源
    最近更新 更多