无法访问在指针数组中创建的对象

Cannot access objects created in array of pointers

本文关键字:创建 对象 数组 指针 访问      更新时间:2023-10-16

我在访问指针数组中创建的对象时遇到问题。我有一些测试代码显示正在创建对象,但在我的ShowCluster()函数中,它挂在通过第二级循环的第一次迭代上。

我认为我对它进行编码的方式是,我有一个Node**对象,它本质上变成了一个2d数组。由于我使用的是new运算符,所以我不必担心函数内部的作用域。

关于为什么我不能显示我创建的这些对象的内容的任何想法。这只是我想用来帮助我理解指针的玩具代码。

主要.cpp

#include <iostream>
#include "Node.h"
void Test(std::string message){
    static int testNumber = 0;
    std::cout << "[+] Test: " << testNumber << " : " << message << std::endl;
    testNumber++;
}
void Default2dNodeArray(Node** myCluster, int height, int width, int vecLength){
    Test("Start of array creation.");
    myCluster = new Node*[height];
    for(int i=0; i<height; i++){
        myCluster[i] = new Node[width];
    }
    Test("End of array creation.");
}
void ShowCluster(Node **myCluster, int height, int width){
    Test("Start of Display array.");
    for(int i=0; i<height; i++){
        Test("Outer for loop");
        for(int j=0; j<width; j++){
            Test("Inner for loop");
            std::cout << myCluster[i][j].myNodeString << " : " << myCluster[i][j].myNodeInt << std::endl;
        }
    }
    Test("End of Display array.");
}

int main(){
    int myHeight = 5;
    int myWidth =8;
    int myVecLength = 4;
    Node** myNodeArray;
    std::cout << "Starting pointer test" << std::endl;
    Test("In main.");
    Default2dNodeArray(myNodeArray, myHeight, myWidth, myVecLength);
    Test("In main.");
    ShowCluster(myNodeArray, myHeight, myWidth);
    Test("In main.");
    std::cout << "Ending pointer test" << std::endl;
    return 1;
}

Node.cpp

#include "Node.h"
#include <stdlib.h>
#include <stdio.h>
#include <sstream>
#include <iostream>

int Node::globalCounter = 0;
Node::Node(){
    std::cout << "Node created." << std::endl;
    std::stringstream ss;
    ss << "Default: " << globalCounter;
    myNodeString = ss.str();;
    myNodeInt = globalCounter;
    myVecLength = new int[3];
    globalCounter++;
}
Node::Node(std::string myString, int myInt, int vecLength){
    myNodeString = "Non-Default:" + myString;
    myNodeInt = globalCounter;
    myVecLength = new int[vecLength];
    globalCounter++;
}

节点.h

#ifndef NODE_H_
#define NODE_H_
#include <string>
class Node {
public:
    static int globalCounter;
    std::string myNodeString;
    int myNodeInt;
    int* myVecLength;
    Node();
    Node(std::string, int, int);

};
#endif /* NODE_H_ */

无论您在Default2dNodeArray函数中对Node** myCluster变量做什么,它在主函数中都不可见,因为您按值传入myCluster。因此main中的myNodeArray不会被修改。如果您想修改它,可以从函数中返回新变量,也可以将函数签名更改为

void Default2dNodeArray(Node**& myCluster, int height, int width, int vecLength)

(注意第一个参数中的引用)。使用三指针也是可能的,但我认为修改传递的变量的意图可以通过引用更好地表达,尤其是因为您已经在处理双指针了。此外,它还保留了代码的其余部分。

您正试图创建一个指向Node对象的指针数组,并初始化每个指向堆上分配的Node对象的指针,然后将其作为参数传递。

将指针传递给函数可以通过值来完成(即指针被复制,您可以通过取消引用它来访问指向的内存,但不能更改原始指针指向的值),通过获取它的地址并将其传递给函数,例如

Node *ptr = 0x10;
function(&ptr);    
void function(Node** ptr_to_ptr) {
    (*ptr_to_ptr) = 0x20; // This will modify ptr
}

或通过引用(也将修改原始指针值)

Node *ptr = 0x10;
function(ptr);    
void function(Node*& ref_to_ptr) {
    ref_to_ptr = 0x20; // This will modify ptr
}

在您的情况下,由于双指针是保持指向Node对象的指针数组所必需的,并且您试图通过获取其地址来传递它,因此最终将使用三指针:

void Default2dNodeArray(Node*** myCluster, int height, int width, int vecLength) {
    Test("Start of array creation.");
    // Dereference to access the original double pointer value
    *myCluster = new Node*[height];
    for (int i = 0; i<height; i++){
        (*myCluster)[i] = new Node[width];
    }
    Test("End of array creation.");
}
void ShowCluster(Node*** myCluster, int height, int width) {
    Test("Start of Display array.");
    for (int i = 0; i<height; i++){
        Test("Outer for loop");
        for (int j = 0; j<width; j++){
            Test("Inner for loop");
            std::cout << (*myCluster)[i][j].myNodeString << std::endl;
        }
    }
    Test("End of Display array.");
}
int main(){
    int myHeight = 5;
    int myWidth = 8;
    int myVecLength = 4;
    Node** myNodeArray; // Double pointer
    std::cout << "Starting pointer test" << std::endl;
    Test("In main.");
    Default2dNodeArray(&myNodeArray, myHeight, myWidth, myVecLength);
    Test("In main.");
    ShowCluster(&myNodeArray, myHeight, myWidth);
    Test("In main.");
    std::cout << "Ending pointer test" << std::endl;
    return 1;
}

上面的签名看起来比实际情况要可怕得多。试着找出我一开始发布的小片段,然后继续阅读这段代码。

如果你理解了上面的例子,就会更容易得到,你也可以通过引用双指针来完成:

void Default2dNodeArray(Node**& myCluster, int height, int width, int vecLength)
// etc..

最后一条建议:尽管这只是一个测试,但记住要释放所有分配的内存,否则会泄露内存!