简体   繁体   English

C++ 重载解引用运算符

[英]C++ overloading dereference operators

I'm relatively new to C++, still trying to get a hang of the syntax.我对 C++ 比较陌生,仍在尝试掌握语法。 I've been taking a look at a few operator overloading examples, most recently smart pointer implementations.我一直在研究一些运算符重载的例子,最近的智能指针实现。 Here's a really generic example I'm looking at:这是我正在查看的一个非常通用的示例:

template < typename T > class SP
{
    private:
    T*    pData; // Generic pointer to be stored
    public:
    SP(T* pValue) : pData(pValue)
    {
    }
    ~SP()
    {
        delete pData;
    }

    T& operator* ()
    {
        return *pData;
    }

    T* operator-> ()
    {
        return pData;
    }
};

When overloading the dereference operator why is the type T&?重载解引用运算符时,为什么类型是 T&? Similarly, when overloading the structure dereference why is the type T*?同样,在重载结构解引用时,为什么类型是 T*?

The dereference operator ( * ) overload works like any other operator overload.取消引用运算符 ( * ) 重载的工作方式与任何其他运算符重载一样。 If you want to be able to modify the dereferenced value, you need to return a non-const reference.如果您希望能够修改解除引用的值,则需要返回一个非常量引用。 This way *sp = value will actually modify the value pointed to by sp.pData and not a temporary value generated by the compiler.这样*sp = value将实际修改sp.pData指向的值,而不是编译器生成的临时值。

The structure dereference operator ( -> ) overload is a special case of operator overloading.结构解引用运算符 ( -> ) 重载是运算符重载的特例。 The operator is actually invoked in a loop until a real pointer is returned, and then that real pointer is dereferenced.该运算符实际上在循环中被调用,直到返回一个真正的指针,然后该真正的指针被取消引用。 I guess this was just the only way they could think of to implement it and it turned out a bit hackish.我想这只是他们能想到的实现它的唯一方法,但结果却有点骇人听闻。 It has some interesting properties, though.不过,它有一些有趣的特性。 Suppose you had the following classes:假设你有以下类:

struct A {
    int foo, bar;
};

struct B {
    A a;
    A *operator->() { return &a; }
};

struct C {
    B b;
    B operator->() { return b; }
};

struct D {
    C c;
    C operator->() { return c; }
};

If you had an object d of type D , calling d->bar would first call D::operator->() , then C::operator->() , and then B::operator->() , which finally returns a real pointer to struct A , and its bar member is dereferenced in the normal manner.如果你有一个D类型的对象d ,调用d->bar将首先调用D::operator->() ,然后是C::operator->() ,然后是B::operator->() ,最后返回一个指向 struct A的实指针,并且它的bar成员以正常方式取消引用。 Note that in the following:请注意,在以下内容中:

struct E1 {
    int foo, bar;
    E1 operator->() { return *this; }
};

Calling e->bar , where e is of type E1 , produces an infinite loop.调用e->bar ,其中eE1类型,会产生一个无限循环。 If you wanted to actually dereference e.bar , you would need to do this:如果您想实际取消引用e.bar ,则需要执行以下操作:

struct E2 {
    int foo, bar;
    E2 *operator->() { return this; }
};

To summarize:总结一下:

  1. When overloading the dereference operator, the type should be T& because that is necessary to modify the value pointed to by pData .当重载解引用运算符时,类型应该是T&因为这是修改pData指向的值所必需的。
  2. When overloading the structure dereference, the type should be T* because this operator is a special case and that is just how it works.当重载结构解引用时,类型应该是T*因为这个运算符是一种特殊情况,这就是它的工作原理。

The purpose of dereference operator is to dereference a pointer and returns the object reference.解引用运算符的目的是解引用一个指针并返回对象引用。 Hence it must return the reference.因此它必须返回引用。 That is why it is T&.这就是为什么它是 T&。

The purpose of referring operator (->) is to return a pointer and hence T* is returned.引用运算符 (->) 的目的是返回一个指针,因此返回 T*。

It is because pointer contains an address of a variable referencing it will give a reference (or to say a lvalue refrence) to the address it has stored.这是因为指针包含引用它的变量的地址,它将提供对它存储的地址的引用(或说左值引用)。 eg int x; int *p; p=&x;例如int x; int *p; p=&x; int x; int *p; p=&x; now x and *p can be used interchangeably.现在x*p可以互换使用。 if you do x =4;如果你做x =4; or *p = 4;*p = 4; both will have same result.两者都会有相同的结果。 *p works as a reference to x just like a normal reference int& t = x; *p用作对x的引用,就像普通引用int& t = x; will work.将工作。

Next thing structure dereference operator. Next thing 结构解引用运算符。 This operator gives you the access of member variables through a pointer to object of a class.该运算符使您可以通过指向类对象的指针访问成员变量。 In above example the member is T* pData;在上面的例子中,成员是T* pData; so using this operator will give access to pData and pData is T* so the return type is T* .所以使用这个运算符可以访问pData并且pDataT*所以返回类型是T* if pData in above example would have been T then the return type would have been T .如果上面示例中的pDataT则返回类型将是T

Overloaded operators are just functions重载运算符只是函数

When overloading operaters you are free to return anything basicly (just like any other function), with the noteable exception of member of pointer -> being somewhat special in this way.当重载操作符时,您基本上可以自由地返回任何内容(就像任何其他函数一样),但指针成员->例外在这种方式中有些特殊。

In the example you show, a smart pointer, you aim to mimick the syntax of a pointer (pointer semantic).在您展示的示例中,智能指针旨在模仿指针的语法(指针语义)。 Then for syntax like:然后对于像这样的语法:

*p = 2;

The indirection operator* return a non-const reference to object and we are able to modify through operator* .间接operator*返回对对象的非常量引用,我们可以通过operator*进行修改。 In effect, usually used for proxy type classes in the same way and it is a sort of a convention - but you could in theory return whatever.实际上,通常以相同的方式用于代理类型类,这是一种约定 - 但理论上您可以返回任何内容。

The member of pointer operator -> is a bit tricky.指针运算符->成员有点棘手。 See this answer for an explanation.请参阅此答案以获取解释。

We are making smart pointer and our aim is to access member of class/structure using any of this T& (reference) or T* (pointer) with flexibility.我们正在制作智能指针,我们的目标是使用任何 T&(引用)或 T*(指针)灵活地访问类/结构的成员。

for T* operator-> ():对于 T* 运算符-> ():

T* operator-> ()
{
  return pData;
}
arrow operator (->) is a shorthand for (*p) and hence we return *pData which is of   type T*. 
here we are Overloding arrow operator so that members of T can be accessed like a pointer.

for T& operator* ():对于 T& 运算符* ():

T& operator* ()
{
  return *pData;
}
    * is "value at address" operator, here we are Overloding * (pointer) operator so 
    that members can be accessed  through a reference (T&).

We can change the behavior of the operator with operator overloading but its not recommended.我们可以通过运算符重载来改变运算符的行为,但不推荐这样做。 overloaded operator behavior should be as close as its basic functionality.重载操作符的行为应该与其基本功能一样接近。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM