简体   繁体   English

将“this”转换为引用指针

[英]Convert “this” to a reference-to-pointer

Let's say I have a struct 假设我有一个结构

struct Foo {
    void bar () {
       do_baz(this);
    }
    /* See edit below
    void do_baz(Foo*& pFoo) {
       pFoo->p_sub_foo = new Foo; // for example
    }
    */

    Foo* p_sub_foo;
}

GCC tells me that 海湾合作委员会告诉我

temp.cpp: In member function ‘void Foo::bar()’:
temp.cpp:3: error: no matching function for call to ‘Foo::do_baz(Foo* const)’
temp.cpp:5: note: candidates are: void Foo::do_baz(Foo*&)

So, how do I convert what is apparently a const Foo* to a Foo*& ? 那么,我如何将显然是一个const Foo*转换为Foo*&

EDIT : I didn't use a very good example. 编辑 :我没有用一个很好的例子。 do_baz should read do_baz应该阅读

void do_baz(Foo*& pFoo) {
    if (pFoo == NULL) {
        pFoo = new Foo;
        return;
    }
    //other stuff
    do_baz(pFoo->p_sub_foo);
    //more stuff
}

You can't. 你不能。

Firstly, this is not necessarily a const Foo * . 首先, this不一定是const Foo * this would be a const Foo * is a const method of the class Foo . this将是一个const Foo *是类Foo的const方法。 In a non-const method this is just Foo * . 在非const方法中, this只是Foo * (Actually your error message mentions Foo* const . Where did you see const Foo * ?) (实际上你的错误信息提到了Foo* const 。你在哪里看到const Foo * ?)

Secondly, and more importantly, this is not an lvalue. 其次,更重要的是, this不是左值。 You can't have a pointer to this . 你不能指向this You can't have a non-constant reference to this . 你不能有非经常提及this The only thing that you can have is a const reverence to this , ie a reference of type Foo *const & . 你可以拥有的唯一的事情是一个const崇敬this ,即类型的参考Foo *const &

It ( Foo *const & ) will work in your case. 它( Foo *const & )将适用于您的情况。

void do_baz(Foo* const& pFoo) { 
   pFoo->p_sub_foo = new Foo;
} 

But I don't see the point of all this. 但我没有看到这一切的重点。 Just declare a normal Foo * pointer as parameter for your do_baz method 只需声明一个普通的Foo *指针作为do_baz方法的参数

void do_baz(Foo* pFoo) { 
   pFoo->p_sub_foo = new Foo;
} 

and get the same result. 并得到相同的结果。 What do you think you need that reference for? 你认为你需要什么参考?

EDIT : Taking into account your edit, what you are trying to do cannot be done with a single do_baz function, since in the first call you'd potentially (semantically) attempt to modify this , which is impossible (even if the modifying code will never be executed in practice). 编辑 :考虑到你的编辑,你想要做的事情不能用一个do_baz函数完成,因为在第一次调用你可能(语义上)尝试修改this ,这是不可能的(即使修改代码将永远不会在实践中执行)。 Whether you want it or not, you can't have a non-const reference to this , even if you don't intend to write anything through it. 不管你愿意不愿意,你不能有一个非const引用到this ,即使你不打算写过任何事情。 You'll probably have to implement the very first call with a different function 您可能必须使用不同的函数实现第一个调用

void do_baz(Foo*& pFoo) { 
  if (pFoo == NULL) { 
    pFoo = new Foo; 
    return; 
  } 
  //other stuff 
  do_baz(pFoo->p_sub_foo); 
  //more stuff 
} 

void do_baz_root(Foo* pFoo) { 
  assert(pFoo != NULL);
  //other stuff 
  do_baz(pFoo->p_sub_foo); 
  //more stuff 
} 

and then make the first call as 然后拨打第一个电话

void bar() {
  do_baz_root(this);
}

Give the variable a name, and then you will have a pointer reference type: 给变量一个名称,然后你将有一个指针引用类型:

void bar () {
   Foo* me = this;
   do_baz(me);
}

I should also point out that your do_baz function isn't making use of the fact that its parameter is a reference (you are not assigning to the pointer, itself, only to what is being pointed to by the pointer). 我还应该指出,你的do_baz函数没有利用它的参数是一个引用这一事实(你不是指向指针本身,只指向指针指向的指针)。 Consequently, it really makes more sense to change the type of the parameter to Foo* instead of Foo*&, or to make it a Foo&, in which case you would use dot (.) instead of arrow (->) when dereferencing the parameter's member. 因此,将参数的类型更改为Foo *而不是Foo *&,或者使其成为Foo&更有意义,在这种情况下,在取消引用时,您将使用点(。)而不是箭头( - >)参数的成员。

Edit 编辑
Your new version of do_baz now makes use of the fact that the parameter is a reference. 您的新版do_baz现在使用参数是参考的事实。 The solution above (simply using a named pointer) will still work for your new version of the problem. 上面的解决方案(只使用命名指针)仍然适用于您的新版本的问题。 That said, I would advise against what you are doing. 那就是说,我会反对你在做什么。 It seems you are trying to insert an element at the end of a linked list... 看来你试图在链表的末尾插入一个元素......

Firstly, I would advise that if you are implementing a linked list that you maintain not only a pointer to the first node in the list, but also a pointer to the last node in the list at all times, so that insertion at the end of the list may be performed in constant-time. 首先,我建议如果你正在实现一个链表,你不仅要维护列表中第一个节点的指针,还要指向列表中最后一个节点的指针,以便在结尾处插入列表可以在恒定时间内执行。 If, however, that is not a possibility, I would nevertheless advise you to use an iterative implementation rather than a recursive one as it is cleaner and simpler. 但是,如果这不可能,我会建议您使用迭代实现而不是递归实现,因为它更简洁。 It would look like: 它看起来像:

Foo* current=this;
while (current->next != NULL){
    current=current->next;
}
current->next = new Foo;

The keyword this is not an lvalue so this can't be assigned to/changed (regardless of whether what it points to is const or not). 关键字this不是左值那么this不能被分配到/改变(无论是否它所指向的是const或没有)。 In other words, you might be able to change what this points to, but you can't change the value of this itself. 换句话说,你也许能够改变什么this点,但你不能改变的值, this本身。 The C++ standard 9.3.2 "The this pointer": C ++标准9.3.2“ this指针”:

In the body of a nonstatic (9.3) member function, the keyword this is a non-lvalue expression 在非静态(9.3)成员函数的主体中,关键字this是非左值表达式

Only const references can bind to non-lvalue objects, so you'd need to bind it to a Foo* const& if you want to bind the this pointer to a reference. 只有const引用可以绑定到非左值对象,因此如果要将this指针绑定到引用Foo* const&则需要将其绑定到Foo* const&

Change the signature of the function to: 将函数的签名更改为:

void do_baz(Foo* const& pFoo);

You don't. 你没有。

this is a Foo* const , meaning it is a const pointer to a non- const Foo . this是一个Foo* const ,意思是它是一个指向非const Fooconst指针。 Your reference is non-const, so the correct declaration would be a Foo* const & . 你的引用是非const的,所以正确的声明将是Foo* const &

But it doesn't make any sense to do this, so don't. 但这样做没有任何意义,所以不要这样做。

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

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