如何禁止调用临时对象的成员函数(C++)

How forbid to call member function for temporary object (C++)

我有模板 class data_ptr,其中的成员 operator * 用于访问数据指针:

operator T*() { return m_pPtr; }

同样在 data_ptr 的构造函数中,它的指针在内存中是 "pinned",在析构函数中是 "unpinned".

我想禁止使用operator*是这样的:

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

...因为函数GetSomeDataPtr returns 临时对象data_ptr,并且当析构函数被调用时它的数据指针变得无效,所以我们在访问时发生崩溃pRawPointerToData.

所以,主要思路是使用编译器来查找这样的代码。我正在使用 Visual Studio 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;
}

您可以使用 左值引用限定符 声明 operator T*,即

operator T*() & { return p; } 

以便只能对 data_ptr 的左值调用此转换,这意味着禁止临时(右值)调用此转换。

您的设计也存在一些缺陷。即使一个对象不是临时对象,它也会在稍后的某个时间被销毁,而之前暴露的那些T*不知道销毁,这有潜在的无效访问的危险。因此,调用者有责任保证没有无效访问,因此您不必限制对临时对象的调用。例如,std::string::c_str 没有此类限制。