2017-09-23 75 views
0

我剛剛開始使用C++進行編程,並且發現了一個尷尬的問題。基本上:C++類成員充當本地變量

  • 我有一個類的成員是一個char[MAX_LEN]包含文件的完整路徑。
  • 我有一個(char*)指向文件的名稱(沒有完整路徑)。

當我構造這個類時,我發現(char*)指針實際上指向構造函數內的局部變量,從而獲得錯誤的結果。

準確地說,類是:

class File_t{ 
    public: 
    char  fullPath[1024]; 
    char*   name; 

File_t(){}; // Default constructor 
File_t(const char* fullPath_){ 
    /* Copy the input name on fullPath */ 
    strncpy(fullPath, fullPath_, sizeof(fullPath)); 

    /* Auxiliary variable to remove the path */ 
    char* auxstr=fullPath; 
    name = auxstr; 

    /* Loop to remove the path */ 
    while(1){ 
     auxstr = strstr(auxstr,"/"); 
     if(auxstr){auxstr=auxstr+1; name=auxstr;} 
     else{break;} 
    } 
} 
}; 

並且,例如,主要在於創造「File_t」的幾個實例,並與幾個文件填充/一些/路徑/ foo1,2,...

int main(int argc, char* argv[]){ 

    const int N = 3; 
    File_t CC[N]; 
    char fileName[100]; 

    for (int i = 0; i < N; i++){ 
    sprintf(fileName,"%s%d","some/path/foo",i); 
    CC[i] = File_t(&fileName[0]); 
    } 


    cout << "Summary" << endl; 
    for (int i=0; i<N; i++) cout << "File " << CC[i].name << " in " << CC[i].fullPath << endl; 


    return 0; 
} 

程序輸出是:

File foo2 in some/path/foo0 
File foo2 in some/path/foo1 
File foo2 in some/path/foo2 

也就是說,名點,一些局部變量構造函數。我在Apple,GNU和Intel編譯器中遇到了這個問題。 PS:我知道我應該避免在C++中使用C風格的字符串,但這只是爲了學習C++基礎知識。

+1

切勿使用'strncpy'。 – melpomene

+0

感謝您的評論。我試過strcpy,問題依然存在。感謝您的回答! –

+0

而不是使用'strstr()',使用'strrchr()' - 找出一個字符(而不是一個字符的字符串)的最右邊。請注意,您可能需要擔心帶有尾部斜線('strrchr()'或'strstr()')的'「/ abc/def/ghi //」'。不過,總的來說,你似乎發現人們推薦C++中不使用C風格字符串的原因之一。他們很容易被濫用。 –

回答

5

代碼中的問題是一箇中斷的賦值運算符(和複製構造函數)。在這一行:

CC[i] = File_t(&fileName[0]); 

你構建一個臨時File_t對象,然後將其分配給CC[i]fullPath是一個數組,因此所有元素都被複制。這可以。但name是一個指針,所以唯一被複制的是指針本身。這是一個問題,因爲它仍然指向臨時對象的fullPath

在本聲明結束時,臨時對象被銷燬。現在CC[i].name是一個無效的指針。

要解決這個問題,請定義一個適當的賦值運算符。它可能會這樣做:

strcpy(fullPath, other.fullPath); 
name = fullPath + (other.name - other.fullPath); 
+0

你是對的!謝謝! –

0

Melpomene有答案。沒有指出複製過程,指針指向局部變量。

如果添加複製過程(以下他的建議):

File_t& operator=(const File_t& other) 
{ 
    strcpy(fullPath, other.fullPath); 
    name = &fullPath[0] + (other.name - &other.fullPath[0]); 
    return *this; 
} 

然後程序工作。

謝謝大家的答案!