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

问题描述 投票:-1回答:1

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

operator T*() { return m_pPtr; }

data_ptr的构造函数内部,它的指针在内存中“固定”,在析构函数中是“未固定”。

我想以这种方式禁止使用operator*

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

...因为函数GetSomeDataPtr返回临时对象data_ptr,并且当析构函数被调用时,其数据指针变为无效,因此我们在访问pRawPointerToData时会崩溃。

因此,主要思想是使用编译器来查找这样的代码。我正在使用Visual Studio 2015 Update 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;
}
c++ lvalue
1个回答
1
投票

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

operator T*() & { return p; } 

因此,只能为data_ptr的左值调用此转换,这意味着禁止临时(rvalue)调用此转换。

您的设计也存在一些缺陷。即使一个物体不是暂时的,它也会在某个时间被破坏,而之前暴露的那些T*s不知道破坏,这可能导致无效访问。因此,调用者有责任保证不会进行无效访问,因此您不必为临时对象限制此调用。例如,std::string::c_str没有这样的限制。

© www.soinside.com 2019 - 2024. All rights reserved.