2013-06-21 2 views
3

내 프로그램에서 다양한 모양을 그리고 모양에 이벤트를 추가하는 데 사용되는 특정 클래스가있었습니다. (방법에 addRegularshape) 위의 코드에서, I는 vector 컬렉션에 추가하기 전에 다른 방법을 참조함으로써 quad 전달하고 있음을메서드에서 포인터 반환

vector<XQuad*> _inputMappedShape; 
void addRegularShape(Container inputPoints, Container outputPoints){ 
XQuad quad; 
setInputPoints(quad, somePoints); 
setInputPoints(quad, somePoints); 
setArrowHandles(quad, somePoints); 
_inputMappedShape[currentIndex++] = &quad; 
} 

XQuad* getMappedShape(int index){ 
return _inputMappedShape[index]; 
} 

void setInputPoints(XQuad& quad, Point* somePoints); 
void setOutputPoints(XQuad& quad, Point* somePoint); 
void setArrowHandles(XQuad& quad, Point* somePoint); 

통지.

내 주요 프로그램에서 내 목적을 위해 쿼드에 대한 포인터를 반환하는 getMappedShape 메서드를 사용하여 셰이프를 검색하려고했습니다. XQuad* returnedShape = getMappedShape(0)


quad의 메모리 어드레스 addRegularShape 방법으로 할당하고, 주소 (방법 getMappedShape)에서 포인터에 의해 반환되는 체크하고 상기 메모리 어드레스는 동일하다.
그러나 어떻게 든 getMappedShape에서 반환 된 내 XQuad 클래스의 데이터가 올바르지 않습니다 (즉, 다른 세 멤버 함수의 XQuad 참조 객체에서 수정 된 데이터가 아닙니다). 대신 일부 가비지 값이 있습니다. 나는 왜 그것이 일어나고 있었는지에 대한 이유를 발견 할 수 없었고, 메모리가 훼손되거나 뭔가 의심스러워서, 나는 addRegularShape의 참조 객체를 다음과 같이 포인터로 변경했다.
XQuad* quad = new XQuad();

이 후, 프로그램은 올바른 값을 반환하기 시작하지만 난 왜 일어나고에 관해서는 의심의 조금 아직도입니까? 컬렉션에 주소를 추가하는 올바른 방법으로 XQuad 객체를 추가하지 않았습니까? 아니면 메서드가 범위를 벗어나면 개체가 파괴되고 컬렉션에서 실제로 반환되는 값이 가비지 값이되는 범위 문제가 있습니까?

답변

2

정의되지 않은 동작으로 끝날 수 있도록 로컬 개체의 주소를 반환합니다 (함수 호출이 끝날 때 소멸됩니다).

+0

실제로 메소드에서 참조를 반환 할 수 있습니까? 포인터의 명시적인 사용을 피하기 위해 참조를 사용하려고합니다. 예 : 생성자로 초기화 된 개인 변수가있을 수있는 클래스.'int & getTopLeftCornerX (return _pTopLeftX);와 같은 private 변수에 대한 참조를 리턴하는 클래스의 getter 메소드. 여기서 _pTopLeftX는 클래스의 전용 변수이며 클래스 생성자로 초기화됩니다. – user1240679

+0

좋지만 약간의 통증이 심한 OP 팁 : 컴파일러의 경고 수준을 높입니다. 경고를 전혀 발생시키지 않는 코드를 작성하십시오. 예를 들어 gcc는 지역 변수에 대한 참조를 반환하는 것에 대해 경고했을 것입니다. – arne

+0

@ user1240679 : 많은 사례가 있습니다. 예 : 'std :: vector :: at()'는 않습니다. 클래스 메서드는 일반적으로 클래스 데이터 멤버에 대한 참조를 반환 할 수 있습니다. 그들은 한 번의 전화보다 오래 살 수 있습니다. 그러나 귀하의 사례는 전형적인 예입니다. Getters는'const'이어야하며 일반 int를 반환하는 것이 좋습니다. – MSalters

3
_inputMappedShape[currentIndex++] = &quad; 

당신은 _inputMappedShape에 쿼드의 주소를 지정합니다. 그래서 당신은 완전한 프로그램에서이 주소를 얻게 될 것입니다. 그러나 쿼드 객체와 연관된 addRegularShape (...) 데이터의 끝 부분은 범위가 끝날 때 파괴 될 것입니다. _inputMappedShape는 데이터 없음. 우리는 멤버 변수 _inputMappedShape [currentIndex ++] = & 쿼드 로컬 객체 XQuad의 주소를 통과했기 때문에

+0

해당 포인터가 파괴 된 객체를 가리키는 경우 참조는 파괴 된 객체를 나타냅니다. 따라서 원칙적으로 객체에 대한 포인터를 반환 할 수 있으면 객체에 대한 참조를 반환 할 수 있습니다. 실제로 객체를 호출자가 삭제해야하는 경우 포인터 (또는 더 나은 점은 스마트 포인터)를 객체에 반환하려고합니다. – celtschk

3

당신은 쓰레기 값을 받고 있었다.

로컬 변수를 만들 때 항상 기억해야하며 그런 다음 해당 로컬 변수에 할당 된 메모리는 항상 스택에 있습니다. 그래서 함수를 빠져 나가 자마자 스택은 풀리고 현재 _inputMappedShape [currentIndex ++]은 실제로 존재하지 않는 위치를 가리 킵니다.

그러나 연산자를 사용하는 메서드 내에서 변수를 만드는 경우 할당 된 메모리는 더 이상 스택에 없지만 힙에 저장됩니다. 이 경우 함수에서 반환 할 때 스택 해제는 변수 _inputMappedShape [currentIndex ++]에 영향을 미치지 않습니다.