2017-09-23 9 views
0

C++でのプログラミングを開始したばかりですが、厄介な問題が見つかりました。基本的に:ローカル変数として動作するC++クラスメンバ

  • 私は1つのクラスを持っています。メンバーはファイルのフルパスを含む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()'を使う - 1文字の文字列の代わりに、文字の右端の文字列を見つける。''/abc/def/ghi // ''に '' strrchr() ''や '' strstr() ''をつけて)心配する必要があるかもしれないことに注意してください。しかし一般的には、C++でCスタイルの文字列を使用しないことを人々が推奨する理由の1つを見つけたようです。彼らは簡単に誤用される。 –

答えて

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

メルポメンに答えがありました。コピー手順は示されず、ポインタはローカル変数を指していました。

コピー手順は、(彼のアドバイス以下)追加された場合:

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

その後、プログラムが動作します。

お返事ありがとうございます!

関連する問題