2017-12-19 17 views
-1

임시 객체의 멤버 함수 (C++)를 호출하는 방법 금지를 : 그 포인터가 data_ptr의 생성자 내부 또한나는 데이터에 대한 포인터에 액세스하기위한 멤버 <code>operator *</code>이있는 템플릿 클래스 <code>data_ptr</code>이

operator T*() { return m_pPtr; } 

을 "고정 된"메모리와 소멸자는 "고정 해제"됩니다.

나는 operator* 사용 금지하려면이 방법입니다 ...

data_ptr<T> GetSomeDataPtr { return data_ptr<T>(...); } 
T *pRawPointerToData = *GetSomeDataPtr(); 

때문에 임시 객체 data_ptr를 반환하고 소멸자가 호출 될 때 데이터 포인터가 무효가됩니다, 그래서 우리가 얻을 GetSomeDataPtr 기능 pRawPointerToData에 액세스 할 때 충돌이 발생했습니다.

따라서 주요 아이디어는 컴파일러를 사용하여 이러한 코드를 찾는 것입니다. 나는 비주얼 스튜디오를 사용하고 2015 업데이트 3

예 :

template <class T> class data_ptr 
{ 
public: 
    data_ptr(T val) : p(new T(val)) {} 
    ~data_ptr() {delete p;} 

    operator T*() { return p; } 

private: 
    T *p; 
}; 

template <class T> 
data_ptr<T> GetSomeDataPtr(T val) 
{ 
    return data_ptr<T>(val); 
} 

int main() 
{ 
    int &rawReferenceToData = *GetSomeDataPtr<int>(123);  
    rawReferenceToData = 456; // << invalid access to already deleted object! 

    return 0; 
} 
+0

'const' 멤버 함수가 아닌 임시 객체를 호출 할 수 없습니다. 당신이 시도한 것에 대한보다 간결한 예를주고, 왜 그것이 효과가 없었는지 설명하십시오. – user0042

+0

음 ...하지만 당신이 제공 한 코드는'연산자 T *()'를 호출하지 않습니다. 실제로'operator *()'를 호출하는 것처럼 보입니다. 그리고이 텍스트의 뒷부분에서'연산자 * '에 대해서도 이야기합니다. 따라서이 질문에 대한 연산자는 역 참조 (operator *()) 또는 변환 ('operator T *()')입니까? – AnT

+0

전체 코드가 추가되었습니다. – n4meless0nly

답변

1

당신은 즉,이

operator T*() & { return p; } 

이 때문에이 변환이 호출 할 수있는, 좌변 REF-규정operator T*을 선언 할 수 있습니다의 lvalue에만 해당되며 이는 임시 (rvalue)가이 변환을 호출하는 것을 금지한다는 것을 의미합니다.

디자인에 일부 결함이 있습니다. 객체가 임시 객체가 아니더라도 나중에 언젠가는 객체가 파괴되고 이전에 노출 된 객체는 파괴를 알지 못하기 때문에 잘못된 액세스가 발생할 위험이 있습니다. 따라서 유효하지 않은 액세스를 보장하는 것은 호출자의 책임이므로 임시 객체에 대해이 호출을 제한 할 필요가 없습니다. 예를 들어, std::string::c_str에는 이러한 제한이 없습니다.