在C++编程中,指针的使用是一把双刃剑。它提供了对内存的直接访问能力,但同时也带来了潜在的风险。不正确的指针访问可能导致程序崩溃或不可预测的行为。因此,确保指针的正确使用至关重要。本文将探讨如何通过一些常见的实践来安全地访问指针。
通常,通过解引用操作符来访问指针指向的内存。但如果内存位置不再可访问,这可能导致奇怪的结果。为了正确处理不安全的指针,可以采用一些策略。
以下代码片段展示了如何正确处理不安全的指针。使用模板创建了一个名为ToRef的类,该类需要根据所需的指针检查类型和删除策略进行实例化。
template<typename T_TYPE, typename T_RET, typename T_DELETE_POLICY>
class ToRef : public std::tr1::tuple<T_TYPE*const&, T_RET, T_DELETE_POLICY> {
public:
ToRef(T_TYPE*const& p_type, const T_DELETE_POLICY delete_policy)
: std::tr1::tuple<T_TYPE*const&, T_RET, T_DELETE_POLICY>(p_type, p_type!=NULL, delete_policy) {
}
};
这个类非常简单,它在返回对象之前检查指针,而不是返回指针,从而安全地使用它。建议使用r_get()来访问指针的对象,而p_get()仅用于跟踪和继承目的。
ToRef类通过模板实现,它封装了指针的有效性检查和删除策略。如果需要根据指针检查策略更改有效性检查,只需更改ToRef实例化并适当定义is_valid()即可。
使用ToRef类非常简单。可以使用宏safe_access_start()和safe_access_end来访问指针。这会在每次访问指针时进行一些额外的有效性检查。另一种选择是使用fast_access_start和fast_access_end,如果存在无效指针,它将处理异常。
// 仅访问,不删除内存
{
Stest *sTest = new Stest(10);
sa::ToRef<Stest, bool, bool> testRef(sTest, false);
safe_access_start(testRef)
testRef.r_get().access();
safe_access_end
}
如果指针无效,ToNRef模板类解决了另一个问题,即如果指针无效,则希望用默认构造函数初始化指针。这也可以与有效性检查和删除策略结合使用。
ToNRef类提供了一种机制,当指针无效时,可以使用默认构造函数初始化指针。
template<typename T_TYPE, typename T_RET, typename T_DELETE_POLICY>
class ToNRef : public std::tr1::tuple<T_TYPE*&, T_RET, T_DELETE_POLICY> {
public:
ToNRef(T_TYPE*& p_type, const T_DELETE_POLICY delete_policy)
: std::tr1::tuple<T_TYPE*&, T_RET, T_DELETE_POLICY>(p_type, (p_type== NULL? p_type=new T_TYPE(1):p_type)!=NULL, delete_policy) {
}
};
然而,这种方法有一些缺点。代码不是线程安全的,因此如果代码打算在多线程环境中使用,需要显式处理原子性。具有删除策略的代码不适用于共享指针。