2016-08-26 9 views
0

私はC++を学びたいと思います。私の初心者の質問です。入れ子構造体についてC++

#include <iostream> 
#include <string> 

using std::cout; 
using std::endl; 

struct student{ 
    struct address{ 
     int no; 
     std::string city; //problem is here 
    }; 

    char grade; 
    int num; 
    address *addr; 
}; 

int main(){ 

    student st1; 
    student *pSt1 = &st1; 

    pSt1->grade = 'A'; 
    pSt1->num = 1234; 

    pSt1->addr->no = 123; 
    pSt1->addr->city = "Imladris"; 

    return 0; 
} 

それはクラッシュしますが、私はこのようstd::string cityを変更した場合:

struct student{ 
    struct address{ 
     std::string city; // here 
     int no; 
    }; 

    char grade; 
    int num; 
    address *addr; 
}; 

それがクラッシュし、いずれの場合も0 ... んが、エラーや警告を返しません。 多分、ここでポインタを使う必要はありませんが、私が言ったように、私はC++を学んでいます。これはポインタ/構造体のサンプルコードです。

私はそれを修正する方法を知っていますが、なぜそれが壊れているのか理解したいと思います。私は文字列都市の宣言順序を変更し、クラッシュしません。どうして?

+4

警告でコンパイルし、コンパイラを聞きます。 – Nelfeal

+3

そして、「動作する」と「動作しない」という意味(コンパイルエラー、プログラムクラッシュ、予期しない結果など)を説明してください。 – SJuan76

+1

「動作するかどうか」という意味は何ですか?私たちにコンパイラのエラーやsthを表示してください。 –

答えて

1

あなたはちょうど用語Undefined behaviorに出くわしました。あなたのコードの最終結果はコンパイラとプラットフォームに依存します。値が指定されていないポインタの逆参照は、操作の結果を予測できない場合の1つと考えられる(前述のように、here)。

0

あなたの入れ子構造を保つが、あなたのメンバ変数の宣言にこれを追加します。

address *addr = new address();

それとももっと良い方法が挙げユーザー@tobi303としてそれを使用することです:ポインタとしてそれを宣言しないでください、ちょうど

address addr;

しかし、このようにそれを使用します:

0123の代わり addressのインスタンス
pSt1->addr.no = 123; // set 
pSt1->addr.city = "Imladris"; // set 
+1

は、メンバーの 'addr'をポインタにする必要はまったくないということに言及する価値があります。 – user463035818

+0

@ tobi303それは"おそらくポインタを使う必要はありませんが、私が言ったように、私はC++を学びます。おそらく本からの運動です。 –

+1

@AdrianJałoszewski私は、OPが "ポインタが必要ないかもしれない"と言うとき、彼は必要ではない 'pSt1'を指していると思います。 'address'がポインタである必要はないという事実は、あまり明白でないかもしれません。もしそれが本から取られれば、まあ、本でもナンセンスを見つけることができます。 – user463035818