2014-11-03 86 views
1

我無法訪問已在指針數組中創建的對象。我有一些測試代碼顯示對象正在創建,但在我的ShowCluster()函數中,它通過第二級循環的第一次迭代掛起。無法訪問在指針數組中創建的對象

我相信我有它編碼的方式是,我有一個Node **對象,實質上成爲一個二維數組。由於我使用的是new運算符,因此我不必擔心函數內部的範圍。

關於爲什麼我不能顯示我創建的這些對象的內容的任何想法。這只是我想用來幫助我理解指針的玩具代碼。

Main.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++; 
} 

Node.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_ */ 
+0

http://markgodwin.blogspot.com/2009/08/c-reference-to-pointer.html – NDEthos 2014-11-03 22:00:48

回答

1

不管你做什麼在Default2dNodeArray功能您Node** myCluster變量,它不會是在你的主要功能中可見,因爲你通過了myCluster值。因此main中的myNodeArray將不會被修改。如果要修改它,請從函數返回新變量,或者將函數簽名更改爲

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

(注意第一個參數中的引用)。使用三指針也是可以的,但我認爲修改傳入變量的意圖通過引用得到了更好的表達,特別是因爲您已經在這裏處理雙指針了。此外,它保持代碼的其餘部分不變。

+0

因此,如果我不使用「新」運算符,我可以只傳遞指針,因爲我有它,然後改變對象的成員,同時在我退出函數時保留這些更改? – NDEthos 2014-11-03 22:02:45

+0

即使您只通過值傳遞,仍會保留低於myCluster級別的所有內容。 'myCluster'指向指針數組的第一個元素。該數組中的每個指針都指向「Node」對象數組的第一個元素。您可以更改指針數組中的指針,您可以更改它們指向包含的數組中的「Node」對象。但是(沒有引用),你不能在函數之外改變'myCluster'的值(即你的情況下'myNodeArray')。 main中的'myNodeArray'保持未初始化並指向垃圾。 – Oguk 2014-11-04 00:51:27

+0

即使未初始化,如果你堅持按值傳遞給函數,myNodeArray必須指向某些有效的東西(至少指向一個指針數組,即Node *),因爲你不能改變它的指向至。但是,我認爲以這種方式分配分配工作是一個壞主意。沒有使用引用的更一致的想法是不會從主函數傳遞'myNodeArray',而是使'Default2dNodeArray' * return *指向新(和完全)分配數組的'Node **'。然後用該返回值初始化'myNodeArray'。 – Oguk 2014-11-04 00:54:15

0

您正在嘗試創建一個指向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.. 

最後一個忠告:雖然這僅僅是一個測試,記得釋放所有分配的內存,否則最終會泄漏它!