常量引用包装器

Constant Reference Wrapper

本文关键字:包装 引用 常量      更新时间:2023-10-16

我在Mark Allen Weiss关于数据结构的书中遇到了以下一段代码。

template <class Object>
class Cref
{
public:
Cref ( ) : obj ( NULL ) { }
explicit Cref( const Object & x ) : obj ( &x ) {
const Object & get( ) const
{
if ( isNull( ) )
  throw NullPointerException( ) ;
else
 return *obj;
}
bool isNull( ) const
( return obj == NULL; }
private:
const Object *obj;
};

所以这里的重点是分配 null/初始化一个常量引用。但我不确定我是否理解以下内容:1. 我们用另一个常量引用 x 初始化一个常量引用。但是为什么它又作为 obj(&x( 完成?&in const Object & x 与 obj(&x( 中的 &x 不同?我看到了这一点,但不是很清楚为什么会这样。请解释一下。2. get 方法(( - 我们尝试返回此类的私有成员 obj 的 const 引用。它已经是一个常量引用。为什么返回 *obj 而不仅仅是 obj ?3. 为什么是显式关键字?如果发生隐式类型转换,会发生什么?有人可以为此提供场景吗?

谢谢

  1. 成员obj的类型为 Object* ,但构造函数接受引用。因此,要获取指针,必须应用地址运算符 & 。成员是一个指针,因为它可以是 NULL(在默认构造函数中设置(,而引用永远不能为 NULL。

  2. 私有成员不是常量引用,而是常量引用。取消引用它以获取引用。

  3. 在这种特定情况下,我也看不到潜在的隐式转换的任何负面影响。

1( obj(&x) 中的&x用作地址运算符。

2(不,这是一个指针。它的时间是Object *,而不是Object &

3( 防止从不兼容的指针类型进行转换,这些指针类型可能具有自己的类型转换运算符。

C++有三种可用的 null 版本:

  • NULL - 过时;仅用于检查返回指针的 C 函数的返回值
  • 0 - 已弃用;文本零在标准中定义为空指针
  • nullptr - 从 C++11 开始,这是测试 null 的首选方法。此外,nullptr_t 是类型安全的 null。

1(令牌&有三个含义:

  • 一元地址运算符:获取任何左值表达式的地址,并提供指向该对象的指针。
  • 引用
  • 符号:在声明中,表示引用类型。
  • 二进制按位 AND 运算符 - 此处不使用

因此,重要的是要知道您是在查看声明还是表达式。

explicit Cref( const Object & x )

在这里,符号出现在函数参数的声明中,这意味着参数的类型x是对const Object的引用。

: obj ( &x ) {}

此处,运算符用于成员初始值设定项表达式。 成员obj被初始化为指向x 的指针。

2( 由于成员 obj 实际上是一个指针,因此需要取消引用运算符一元*来获取引用。

3(一般来说,在任何可以只接受一个参数的(非复制(构造函数上使用explicit是个好主意。 不幸的是,该语言不会默认为显式,而是让您在有意使用时使用某种"隐式"关键字。 在这种情况下,如果构造函数是隐式的,可能会发生一件相当糟糕的事情:

Object create_obj();
void setup_ref(Cref& ref) {
    ref = create_obj();
}

没有编译器错误或警告,但该setup_ref函数存储指向临时对象的指针,该指针在函数返回时无效!

1(obj的类型不是引用,obj是指针,const指针必须使用地址初始化,因此必须应用address-of运算符&。2( get(( 方法返回的引用不是对类成员 obj 的引用,而是对 obj 指向的对象的引用,因此您必须使用 * 来尊重它。3(关键字显式表示我们拒绝隐式转换,也就是说,我们告诉编译器,不要为我们使用此构造函数进行隐式转换。
例:

class Cref<Object> A;
Object B;
A=B;

没有显式也没关系 - 由于我们需要右侧的 Cref 对象,编译器将使用构造函数 Cref( const Object & B( 自动制作 Cref 对象。但是,如果添加显式,编译器将不会进行转换,并且会出现编译错误。