3

このエラーは実行時に発生しますが、何が原因なのかわかりません。コードは正しいように見えます。

#include <iostream>
#include <string>

using namespace std;

struct Room {
    int d_noSeat;
    bool d_hasProjector;
    Room() = default;
    Room(const Room& r);
};

class Event {
    Room* d_room;
    std::string d_name;
public:
    Event();
    Event(const Event& e);
    ~Event();
    void set(Room r, const std::string& name);
    void print();
};

Event::Event() : d_room(0), d_name("") {};

void Event::print() {
    std::cout << "Event: " << d_name;
    if (d_room != 0) {
        std::cout << " in size " << d_room->d_noSeat;
        if (d_room->d_hasProjector)
            std::cout << " with";
        else
            std::cout << " without";
        std::cout << " projector";
    }
    std::cout << std::endl;
    return;
}

void printEvent(Event e) {
    e.print();
    return;
}


void Event::set(Room r, const std::string& name) {
    d_room = &r;
    d_name = name;
}

// Room shallow copy constructor
Room::Room(const Room& r) : 
    d_noSeat(r.d_noSeat), 
    d_hasProjector(r.d_hasProjector)
{ }

// Event deep copy constructor
Event::Event(const Event& e) : 
    d_name(e.d_name), 
    d_room(new Room(*e.d_room))
{ }

// Event destructor
Event::~Event()
{
    delete[] d_room;
}


int main() {
    const int noLect = 5;
    Room r;
    Event lectures[noLect];

    for (int i = 0; i < noLect; ++i) {
        r.d_noSeat = i + 1;
        r.d_hasProjector != r.d_hasProjector;
        lectures[i].set(r, "CSI2372");
        lectures[i].print();
    }
    std::cout << "-------------------" << std::endl;
    for (int i = 0; i < noLect; ++i) {
        printEvent(lectures[i]);
    }
    return 0;
}

エラーは明らかに 52 行目 (print() 関数の最初の行) で発生します。これに加えて、印刷されたテキストには、非常に大きく、多くの場合負の数値が表示されます。これは何が原因ですか?

4

2 に答える 2

9

問題

void Event::set(Room r, const std::string& name) 
{
    d_room = &r;
    //      ^
    d_name = name;
}

Room rスコープの最後で破棄される一時オブジェクト: 値渡しを参照しています: }

代わりに、メンバー ポインターを再割り当てする必要があります。

d_room = new Room(r);

なぜうまくいかなかったのか

C++クラスでCスタイルのコードを書いているからです。

C++ では、次の傾向があります。

  1. ネイキッド ポインターを避け、スマート ポインターを優先します。

    class Event 
    {
        std::shared_ptr<Room> d_room;
     ...
    
    Event::~Event() { /* no need to delete */ }
    
  2. setコンストラクターのオーバーロードを使用します (構築後に -like 関数を使用する代わりに):

    Event(Room& r, const std::string& name):
            d_room(new Room(r)),
            d_name(name)
    {}
    
  3. 参照渡し:

    void set(Room& r, const std::string& name);
    
  4. 生の配列を避け、代わりに STL 機能を使用します。

    std::vector<Event> lectures;
    // or
    std::array<Event, 5> lectures;
    

別の問題

r.d_hasProjector != r.d_hasProjector; // checks if r.d_hasProject is not itself

あなたはおそらくしたいです

r.d_hasProjector = !r.d_hasProjector;

完全なコード: リンク

また、高度な C++ に関する必読のリンクがあり、非常に役立つと思います: http://www.parashift.com/c++-faq/

編集:あなたの質問を忘れていました:

これに加えて、印刷されたテキストには、非常に大きく、多くの場合負の数値が表示されます。これは何が原因ですか?

それらの数字はゴミです。明示的に初期化されていない変数は、まったく初期化されません。メモリが割り当てられますが、以前のプログラムからの古い情報が保持されます。それは何でも含むことができます。初期化されていない変数から読み取ると、このガベージが得られます。破壊されたオブジェクトを指しているポインターがありました。したがって、ポインターは実質的に初期化されていません。

于 2013-10-30T17:58:16.387 に答える
1

あなたの問題はここにあります:

void Event::set(Room r, const std::string& name) {
    d_room = &r;
    d_name = name;
}

&r、関数が戻るときに有効期間が終了するオブジェクトのアドレスを取得するため、後でアクセスしようとしたときに未定義の動作が発生します。

ポインターを使用する場合は、動的に割り当てる必要があります。

void Event::set(Room* r, const std::string& name) {
    d_room = r;
    d_name = name;
}

// ...
for (int i = 0; i < noLect; ++i) {
    Room* r = new Room;
    r->d_noSeat = i + 1;
    r->d_hasProjector != r.d_hasProjector;
    lectures[i].set(r, "CSI2372");
    lectures[i].print();
}
// ...

しかし、ここでポインターが必要なようには見えません。

Room d_room;

Eventクラスで。

于 2013-10-30T17:36:57.883 に答える