【问题标题】:C++ -- Pointers to Arrays -- Arrays of PointersC++ -- 指向数组的指针 -- 指针数组
【发布时间】:2009-12-01 21:39:47
【问题描述】:

我注意到这让一些人感到困惑,但在阅读了这里的几篇帖子和 cplusplus 教程后,我的大脑仍然混乱。

假设我在头文件中有以下变量-

int numberOfLinePoints;
D3DXVECTOR3* line;   //confused as to what it is

然后在实现 C++ 文件中我将它们初始化如下 -

//both initialized in constructor
numberOfLinePoints = 25;
line = new D3DXVECTOR3[numPoints];   //array of pointers?

我的 line 变量现在代表什么?

据我从阅读 stackoverflow 上的链接可以看出,它应该代表一个指针数组。然后我阅读了以下内容......

(1) Pointers for Beginners

...其中 (A) 指针数组和 (B) 指向数组的指针都进行了讨论。这让我再次感到困惑,因为它们的工作方式似乎相似。

我在一个单独的位置定义我的指针到我分配它们的位置(正确吗?)这一事实似乎是我困惑的根源。 我是否正确,这是指向 D3DXVECTOR3 对象的指针数组?

完成 - 如果变量 line 包含有关一条线段的信息,我将如何创建一个线段数组?我目前有以下 -

//HEADER FILE
int numberOfLineSegments;
D3DXVECTOR3** lineCollection;   //array of pointers - each of which
                                //points to an array of pointers?
//CPP FILE
numberOfLineSegments = 8;                            //constructor
for(i = 0; i < numberOfLineSegments; i++)            //initialization
{                                                    //and allocation  CORRECT?
   lineCollection[i] = new D3DXVECTOR*[numPoints];   //of memory for     Y/N
}                                                    //lineCollection

VOID createLineSegments(startPoint, endPoint) //could return array instead
{
//pseudo to generate one line segment
while != numberOfLinePoints
line[sentinel++] = interpolate(startPoint, endPoint, time_T)

//pseudo to generate array of line segments
while != numberOfLines
lineCollection[sentinel++] = line
}

非常感谢任何帮助。

【问题讨论】:

  • 你永远不会在头文件中声明变量的存储。您的“头文件”行必须全部位于 CPP 文件的顶部。标头用于声明事物存在的抽象潜力,而不是它们的实际存储,或者它们在您的实际程序中使用或存在的现实。
  • 我不知道。在我的课程中,我一直被教导对象的声明放在对象头中,并在 CPP 文件中初始化。我会和我的一位导师一起提出这个问题,谢谢。

标签: c++ arrays pointers


【解决方案1】:

你的第一个例子:

int numberOfLinePoints;
D3DXVECTOR3* line;   //confused as to what it is

声明一个指向 D3DXVECTOR3 的简单指针。可以通过两种方式初始化指针。第一:

line = new D3DXVECTOR3;

这将创建一个 D3DXVECTOR3 并使线指向该对象。第二:

line = new D3DXVECTOR3[numberOfLinePoints];

这将创建一个 D3DXVECTOR3 数组,并使 line 指向该数组的第一个元素。然后,您可以使用指针算法来访问该数组中的其他元素。

如果将指针声明为双指针:

D3DXVECTOR3** line;

您只需创建另一个间接级别。

【讨论】:

    【解决方案2】:
    int numberOfLinePoints;
    D3DXVECTOR3* line;   //confused as to what it is
    //both initialized in constructor
    numberOfLinePoints = 25;
    line = new D3DXVECTOR3[numPoints];   //array of pointers?
    

    lineD3DXVECTOR3 的数组。但是,如果D3DVECTOR3 本身就是一个指针,它将是一个指针数组。由于我不太了解 C++ D3D 标头,因此我不确定。

    D3DXVECTOR3** lineCollection;
    

    是一个指针数组,每个指针都可能是指向一行的指针(即D3DXVECTOR3 的数组)。

    你有两个选择。内存方面,最好将lineCollection 中的每个条目设置为仅指向相应的行。如果您知道这些行不会更改(并且不会被释放),或者如果它们确实更改了您希望这些更改立即反映在您的集合中,那么这是安全的。

    另一种选择是为lineCollection 中的每个条目创建一个新数组,并将每个line 中的点复制到这个新数组中。

    没有正确答案,这取决于你想要的功能。

    【讨论】:

    • 谢谢唐尼,这正是我想知道的。所有其他回复也很有帮助,但这可能是我能理解的最清楚的方式。
    【解决方案3】:

    (试图在不引入其他问题的情况下尽可能简洁地回答问题的第一部分。)

    C++(和 C)使用指向数组中单个项目的指针作为整个数组的句柄。但是,有些指针并不指向数组中的项目!您必须自己区分point-to-single-item 和points-to-item-in-array。

    int length = 8;
    D3DXVECTOR3* line = new D3DXVECTOR3[length];
    

    new[] 运算符返回一个指向它分配的数组中第一项的指针,并将该值分配给 line。请注意,因为指针不区分单项与数组中的项:

    • 您必须单独存储长度
    • 您必须小心使用带有指针的正确索引(上面的“行”)
    • 最好使用“真正的”容器类型,例如:
      • std::deque、std::vector 等
      • std::tr1::array(又名 boost::array)

    (最后一个要点并不意味着你从不使用指针,你只是在这些容器更合适的时候不使用它们。)

    【讨论】:

      【解决方案4】:
      D3DXVECTOR3 line; // Line is a D3DXVECTOR3
      D3DXVECTOR3 * line; // Line is EITHER a pointer to D3DXVECTOR3 OR an
                          // array of D3DXVECTOR3
      D3DXVECTOR3 ** line; // Line is an array of pointers to D3DXVECTOR3 OR
                           // an array of array of D3DXVECTOR3
      

      这是因为数组在内存中没有特定的结构。它只是一堆 D3DXVECTOR3 连续。因此,指向第一个元素,您就可以访问所有其他元素。

      所以,有

      D3DXVECTOR3** lineCollection; // An array of pointers OR an array of array!
      new D3DXVECTOR[numPoints]; // A pointer to an array of D3DXVECTOR
      lineCollection[i] // A pointer to an array
      

      您通过以下方式对其进行初始化:

      lineCollection[i] = new D3DXVECTOR[numPoints]; // No extra *
      

      然而:尝试使用 STL(如 std::vector)而不是丑陋的 C/Java 样式数组。如果可以,请避免在堆上声明(使用'new'),而是在堆栈上声明:

      D3DXVECTOR a, b, c; // a, b, and c ARE D3DXVECTOR, not pointers
      std::vector<D3DXVECTOR> lines;
      lines.push_back(a);
      lines.push_back(b);
      lines.push_back(c);
      
      // equivalently: (you can push_back without temporaries)
      std::vector<D3DXVECTOR> lines;
      lines.push_back(D3DXVECTOR());
      lines.push_back(D3DXVECTOR());
      lines.push_back(D3DXVECTOR());
      

      这将避免手动内存管理;它更具可读性。您可能无法始终使用这种舒适性(代码的组织方式)。如果有人说一些关于表演的事情,现在,不要担心。首先让某些东西在没有段错误或内存泄漏的情况下工作。

      【讨论】:

      • AFAIK 编译器可以决定在堆栈上分配对象,即使在使用 new 时,如果程序行为没有改变。不过只是一个旁注。
      • 我错过了这篇文章。实际上,这与唐尼的帮助很大。可惜我不能设置两个正确的答案。谢谢。
      • 很高兴它可以提供帮助。 @Space_cowboy:我对编译器优化知之甚少,我正在寻找一些很好的术语来明确地告诉 name 两种分配方式,因为我对程序员更感兴趣。堆和堆栈会使新用户感到困惑(而且显然也很高级)。这里有什么建议吗?
      • 这是我做过的最“侵入性”的编辑,但“stl::”是一个明显的错误。 (STL 是一个特定的库,不仅仅是 C++ 标准库,甚至不仅仅是其中的模板。)如果这太多了,请道歉。 (我在做的时候还有其他一些小的调整。)重新性能:虽然我同意如果它 不起作用,它的运行速度有多快并不重要,但有这里没有性能差异!向量 一个动态数组,就像你用 new[] 得到的一样,唯一的区别是接口。 (您甚至可以将 &v[0] 作为 C 风格的数组传递。)
      • Space_C0wb0y:虽然是这样,但使用标准中的“as-if 规则”,在实践中很难安排,我不知道有任何尝试的实现。 (编译器必须进行全局分析,以确保您不会编写自己的 operator new ,例如。)如果有这样的实现,我会很想看看他们是如何做到的。
      【解决方案5】:
      line = new D3DXVECTOR3[numPoints];
      

      line保存了D3DXVECTOR3数组第一个元素的内存地址。

      line 是指向数组第一个元素的指针。

      This article 应该澄清一下。

      【讨论】:

        【解决方案6】:

        看看这个简单的例子:

        案例一:

        int *p = new int [N];
        

        这里p是指向N个整数数组的指针,p存储数组的起始地址。

        案例2:

        int **p = new int *[N]; //p is a pointer to pointers holding integers used for 2D array.
        
        
        for(int i=0 ; i<N ; i++)
        {
        
            p[i] = new int [N]; // each element is pointer to array of integers.
        
        }
        

        适用于各种用户自定义类型。

        【讨论】:

          猜你喜欢
          • 2017-08-25
          • 1970-01-01
          • 2013-04-19
          • 2010-10-25
          • 1970-01-01
          • 2023-03-11
          • 2021-02-07
          • 2016-07-30
          相关资源
          最近更新 更多