2017-12-26 65 views
1

ESP8266의 작은 클래스에서 작업 중이며 같은 객체의 다른 인스턴스에서 객체에 대한 참조를 보유 할 수 있어야합니다. 코드를 실행할 때 예외가 발생했습니다. 일부 디버깅 후에는 객체가 여전히 범위 내에있는 동안 클래스 소멸자가 호출되는 것처럼 보입니다. 오랫동안 C++로 작업하지는 않았지만이 동작은 잘못되었습니다.Arduino 클래스 소멸자가 객체가 아직 범위에있는 동안 호출 됨

정말 두 가지 질문이 있습니다.

  1. 개체가 아직 범위에있을 때 소멸자가 호출되는 이유는 무엇입니까?
  2. 소멸자가 호출되지 않고 객체의 범위를 지나서 객체에 대한 참조를 보유 할 수 있습니까 (예 : 링크 된 목록에서)?

나는이 문제를 보여주는 작은 프로그램으로 코드를 축소했습니다. 아래의 코드에서 클래스 소멸자는 여전히 '자식'객체에서 호출됩니다. 코드에서 지적한대로 실제로 두 번 호출됩니다. 여기

코드로부터의 출력이다 :

 
     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

공극 setChild (TestObject 높이)에서; 멤버의 자식 포인터를 임시 주소 (매개 변수)로 설정합니다. 참조 void setChild (TestObject & h)를 전달하려고합니다. 하지만 그때조차도 자식 포인터는 객체의 수명을 연장하기 위해 아무 것도하지 않습니다.

+0

이 현재의 범위를 과거 사는 목록에 저장 될 수 있도록 하나가 개체의 수명주기를 관리 할 수있는 방법에 대한 생각 블록? – user1818726

3

TestObject::setChild값이이며, 따라서 TestObject 사본이 작성되고 함수에 의해 사용 된 다음 파기됩니다. 이것은 여러분이보고있는 소멸자의 근원입니다. setChild 또한 TestObjectchild 포인터가 파괴 된 개체를 참조하도록이 로컬 복사본에 대한 포인터를 사용합니다.

이 솔루션은 참조에 의해 매개 변수를 전달하는 것입니다

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

포인터를 전달하는 것이 더 좋을 것입니다. 함수가 참조로 전달 된 객체에 대한 포인터를 참조로 저장해서는 안됩니다. '&'연산자를 사용하면 호출 사이트는 그들이 지나가고있는 객체의 수명에 대해 생각할 필요가 있음을 알립니다. –