常量参考包装器

时间:2011-11-13 01:32:03

标签: c++ pointers constructor const

我在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(&amp; x)完成了?和&amp;在const对象&amp; x与obj(&amp; x)中的&amp; x不同?我看到了这一点,但不清楚为什么会如此。请解释一下。 2. get方法() - 我们尝试返回此类的私有成员obj的const引用。它已经是一个const引用。为什么返回* obj而不仅仅是obj? 3.为何显式关键字?如果发生隐式类型转换会发生什么?有人能为此提供一个场景吗?

由于

4 个答案:

答案 0 :(得分:1)

1)&x中的obj(&x)用作运营商的地址。

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

3)防止从可能有自己的类型转换操作符的不兼容指针类型进行转换。

C ++有三种可用的null:

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

答案 1 :(得分:1)

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

  2. 私有成员是const引用,而 poinetr 是const。它被取消引用以获得参考。

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

答案 2 :(得分:0)

1)令牌&有三个含义:

  • 一元运算符地址:获取任何左值表达式的地址,给出指向该对象的指针。
  • 参考sigil:在声明中,表示参考类型。
  • 二进制按位AND运算符 - 此处未使用

因此,了解您是在查看声明还是表达方式非常重要。

explicit Cref( const Object & x )

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

: obj ( &x ) {}

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

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

3)一般来说,在任何(非复制)构造函数上使用explicit是个好主意,它可以只接受一个参数。不幸的是,语言并不默认为显式,而是让你使用某种“隐式”关键字代替。在这种情况下,如果构造函数是隐式的,那么这可能会发生一件坏事:

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

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

答案 3 :(得分:0)

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

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

没有显式就没关系 - 因为我们在右侧需要一个Cref对象,编译器将使用构造函数Cref(const Object&amp; B)自动创建一个Cref对象。但是如果你添加一个显式的,编译器就不会进行转换,就会出现编译错误。