2017-12-26 21 views
1

私はESP8266の小さなクラスで作業しており、同じオブジェクトの別のインスタンスのオブジェクトへの参照を保持できる必要があります。コードを実行するとき、私は例外を取得しています。いくつかのデバッグの後、オブジェクトがスコープ内にある間、クラスデストラクタが呼び出されるように見えます。私は長い間C++で作業していませんが、この動作は間違っています。オブジェクトがまだスコープ内にある間に呼び出されるArduinoクラスのデストラクタ

実際には2つの質問があります。

  1. オブジェクトがまだスコープ内にあるときにデストラクタが呼び出されるのはなぜですか?
  2. (リンクされたリストのように)デストラクタを呼び出さずに、オブジェクトのスコープを超えたオブジェクトへの参照を保持することはできますか?

私はこの問題を示す小さなプログラムにコードを縮小しました。下のコードでは、クラスデストラクターはスコープ内にある間に '子'オブジェクトで呼び出されます。私がコードで指摘しているように、実際には2回呼び出されます。

ここでは、コードの出力は次のとおり空隙setChild(TestObjectのh)に

 
     Starting 
     adding child to root 
     Out of scope name=child 
     adding child to root2 
     Out of scope name=child 
     Done, both root and child should still be in scope 
#include "Arduino.h" 

class TestObject { 
    private: 
     char name[20]; 
     TestObject* child; 

    public: 
     TestObject(const char* name); 
     virtual ~TestObject(); 
     void setChild(TestObject h) ; 
     char *getName(); 
}; 

TestObject::TestObject(const char *name) { 
    child = (TestObject*)0; 
    strcpy(this->name,name); 
} 

TestObject::~TestObject() { 
    Serial.println("Out of scope name="+String(name)); 
} 

char *TestObject::getName() { 
    return name; 
} 

void TestObject::setChild(TestObject h) { 
    child = &h; 
    Serial.println("adding "+String(h.name)+" to "+String(name)); 
} 

void setup() { 
    Serial.begin(115200); 
    delay(1000); 
    Serial.println("\nStarting"); 
    TestObject root = TestObject("root"); 
    TestObject child = TestObject("child"); 
    root.setChild(child); // child destructor is called here but it should still be in scope 
    delay(1000); 
    TestObject root2 = TestObject("root2"); 
    root2.setChild(child);// child destructor is called a second time here 
    Serial.println("Done, both root and child should still be in scope"); 
    while(true) { 
    delay(10000); 
    } 
} 

答えて

0

は、メンバの子ポインタを一時的なアドレス(パラメータ)のアドレスに設定します。参照void setChild(TestObject & h)を渡したいと思うかもしれません。それでも子ポインタはオブジェクトのライフタイムを延ばすために何もしません。

+0

それが現在の範囲を超えて生きるリストに保存することができるように、1は、オブジェクトのライフサイクルを管理するかもしれない方法上の任意の考えブロック? – user1818726

3

TestObject::setChildの値がであるため、TestObjectのコピーが作成され、関数によって使用され、破棄されます。これはあなたが見ているデストラクタのソースです。 setChildもこのローカルコピーへのポインタをとり、TestObjectchildポインタが破棄されたオブジェクトを参照するようにします。

ソリューションは参照でパラメータを渡すことです:

void TestObject::setChild(TestObject &h) 
+0

ポインタを渡すほうがよいでしょう。関数は、参照渡しされたオブジェクトへの参照/ポインタを格納すべきではありません。 '&'演算子を使用すると、渡されているオブジェクトの存続期間について考える必要があるコールサイトが警告されます。 –

関連する問題