【问题标题】:Declaring pointer to an integer array C++声明指向整数数组 C++ 的指针
【发布时间】:2012-04-30 02:56:30
【问题描述】:

我想在我的类的头文件中声明一个指向整数数组的指针。我有

private:
 int *theName;

然后在构造函数中

theName = new int[10];

这行得通吗?有没有其他方法可以让你有一个指向数组的指针?

我认为 int *theName 创建了一个指向整数而不是整数数组的指针,如果这创建了一个指向整数数组的指针,你如何创建一个指向整数的指针?

我也可以在析构函数中调用

delete theName; theName = NULL;

这会删除 theName 整数数组对象,然后将 theName 指向内存中的 null 吗?

谢谢

【问题讨论】:

  • 除非你有很好的理由不这样做,否则你应该只使用std::vector
  • 可能不会对这么小的数组进行堆分配。

标签: c++ arrays pointers


【解决方案1】:

四件事:

  • 是的,这就是你如何创建指向数组的指针。请注意,指向整数的指针和指向整数 array 的指针之间没有区别;您可以将整数视为一个元素的数组。如果x 是指向整数的指针,您仍然可以使用x[0],如果x 是指向数组的指针,您仍然可以使用*x,它们的工作方式相同。

  • 其次,你必须使用delete[] theName不是 delete theName。无论你在哪里使用new,你都必须使用delete,无论你在哪里使用new[],你都必须使用delete[]。另外,theName = NULL 也不需要设置,因为在析构函数运行后,你无论如何都无法访问theName

  • 第三,在编写管理资源的类时,需要编写拷贝构造函数、移动构造函数、拷贝赋值运算符和移动赋值运算符。

  • 第四,除非您只是将其作为教学练习,否则您应该真正使用std::vector。它有很多优点,没有真正的缺点。如果您使用vector,您甚至不必编写其他四个构造函数。

【讨论】:

  • 讨厌成为一个书呆子,但这-> “指向整数的指针和指向整数数组的指针之间没有区别” 是不正确的。 知道你的意思,但 OP 可能不知道,如果他从字面上理解你所说的话,这一点势必会让他感到困惑。
  • @BenjaminLindley 如果不写一些巨大且分散注意力的东西,这会影响其余的答案,因为它对初学者来说非常详细和令人困惑,所以很难进入这一点。但是,是的,它并不精确。
  • 我认为这是一个链接到文章、简介或关于主题的问题作为旁注的地方。
  • @chris 不过,我真的不知道任何关于此的文章。如果您知道我(或您)可以编辑答案。
  • 奇怪的是,我在上面找不到任何东西。只有指针数组与指向数组的指针。
【解决方案2】:

我完全犹豫要不要发布这个,但我希望它不会造成问题。

迂腐:大多数其他答案都是错误的:您创建的是不是指向数组的指针。它是一个指向 int 的指针,它指向数组的初始元素。

我犹豫是否发布它,原因很简单,这几乎肯定只是在您的问题中使用了错误的措辞——指向int 的指针几乎肯定是您认为想要的,它就是你真的得到了。

但是,有诸如指向数组的指针之类的东西。它很少有用,因为当/如果你对它进行指针数学运算(包括下标),指向数组的指针会增加它指向的数组的大小。在您的情况下,您分配了 10 个ints。您可以使用指针下标来引用数组中的ints,因此theName[0] 引用第一个inttheName[1] 引用第二个int,依此类推——这正是您通常的做法想要。

如果您正在使用(例如)一个数组数组,并且想要一个可以遍历整行的指针,那么您可能能够真正使用指向数组的指针一次,所以ptr[0] 是第一行,ptr[1] 是第二行,依此类推。例如:

#include <iostream>

static const int x = 20;
static const int y = 10;

int main() {
    char data[y][x];

    auto ptr_array = &data[0];
    char *ptr_char = &data[0][0];

    std::cout << "Address of entire array: " << (void *)data << "\n";

    std::cout << "char *[0] = " << (void *)ptr_char << "\n";
    std::cout << "char *[1] = " << (void *)(ptr_char+1) << "\n";

    std::cout << "array *[0] = " << (void *)ptr_array << "\n";
    std::cout << "array *[1] = " << (void *)(ptr_array+1) << "\n";
    return 0;
}

我已将其更改为使用 char(而不是 int)的数组,以使数学更加明显——sizeof(char) == 1(根据定义),所以它更容易工作出数学。当我在我的机器上运行这段代码时,我得到的地址是:

Address of entire array: 0047FD2C
char *[0] = 0047FD2C
char *[1] = 0047FD2D
array *[0] = 0047FD2C
array *[1] = 0047FD40

如您所见,ptr[0] 将数组的地址作为一个整体保存。然而,使用指向char 的指针,ptr[1] 拥有一个更大的地址。然而,指向数组的指针拥有一个大于 0x40 - 0x2C = 0x14 = 20 的地址——这符合我们给数组 (20) 的 X 维度。换句话说,我们确实有一个指向数组的指针,并且该指针上的指针算术(或等效地,下标)一次只针对整个数组起作用。

我会重复一遍:至少如果我们忽略您几乎肯定应该使用std::vector这一事实,那么您想要的类型和您获得的类型都是pointer to int .有pointer to array 这样的类型,但几乎可以肯定不是想要你真正想要的。

【讨论】:

    【解决方案3】:

    是的,这会起作用。

    你需要写delete[] theName——如果你用new TYPE[]分配,那么你必须用delete[]操作符删除。

    theName 设置为null 是一种很好的形式,尽管在析构函数中是多余的,因为整个对象(因此theName)很快就会不复存在。

    更好的 C++ 方法可能是使用std::vector&lt;int&gt;

    【讨论】:

      【解决方案4】:

      是的,这就是初始化指针的方式。不过你有一些问题:

      1. 您需要调用delete [] 来处理您使用new[] 分配的任何内容。您的代码无法按预期工作并导致 UB。

      2. 您需要实现复制构造函数和赋值运算符。如果该指针被复制到您类型的另一个实例会发生什么?你最终会在它上面调用delete [] 两次。

      3. 术语挑剔:

      这会删除 name 整数数组对象,然后 theName 指向内存中的 null 吗?

      不,它将theName 设置为NULLtheName 是一个变量,与其他任何具有值的变量一样。这个变量恰好是一个地址,所以当这样使用时,是的,它的值将是NULL的数值,不管它是什么。

      【讨论】:

        【解决方案5】:

        有没有其他方法可以让你有一个指向数组的指针?

        您可以使用std::vector。这 [在大多数情况下] 可以插入到您使用数组的任何位置,并提供以下好处:

        1. 无需担心内存管理
        2. 在需要时自动调整大小
        3. 可以继续使用array[index]语法
        4. 可以使用.at() 方法执行边界检查。

        如果你想要一个指向第一个元素的指针(给 C 风格的 API 等),你可以使用:

        std::vector<int> vec(10);
        
        SomeCFunction(&vec[0]);
        

        【讨论】:

          【解决方案6】:

          是的,delete[] 和 vector 和其他东西的答案非常好,但请记住这一点:int* p 是“指向 int 的指针”类型。它确实是一个指向单个整数的指针。但是,如果您像这样取消引用它 p[5] 这与说 *(p + 5) 相同。这也是数组访问的工作原理。 (以及为什么可以将数组隐式转换为指向其第一个元素的指针。)但是,有一个指向数组类型的指针。 int (*p)[10] 是“指向大小为 10 的 int 数组的指针”。然而,这不是你想要的。因为如果现在你会说 p[5] 这意味着 *(p + 5) 将访问地址 p + sizeof *p * 5。但是 sizeof *p 是 sizeof int[10],所以你有乱七八糟的地方。 (当然,p[5] 的类型是 int[10],因为 p 是指向 int[10] 的指针);-)

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-04-30
            • 2011-06-20
            • 2022-08-16
            • 2017-07-16
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多