将指针转换为引用,代价高昂吗?

12

可能是重复问题:
在C++中解引用指针的代价有多大?

如果我有一个指向对象的指针,比如说Object *ptr;,并且我想将它传递给形式为void foo(Object& obj)的方法,我理解我需要编写:

foo(*ptr);

为什么要取消引用ptr呢?直接传递foo(ptr);不是更合理吗?我担心*ptr会复制原始对象,或至少不仅仅将地址传递给foo

有人能帮我解决这个问题吗?对于期望此行为与使用void foo(Object *obj);并通过foo(ptr)调用的函数相同快速执行的代码来说,传递*ptr是否可能成为瓶颈?

5个回答

14

我担心*ptr可能会复制原始对象。

你错了。解除引用指针不会复制任何内容!

void f(Object & obj); //note it takes the argument by reference

Object *ptr = get();

foo(*ptr); 

在这段代码的最后一行没有拷贝。标准规定给你这个保证。

然而,如果f使用值传递的参数,那么就会发生拷贝。

总之,函数参数中的引用通常被用来避免拷贝,有时也被用作输出参数。


14
无论是否会复制 *ptr 取决于被调用的函数是期望一个 Object 还是一个 Object &。如果是前者,将会进行复制,如果是后者(即您的情况),将 不会 进行复制。

因此,通过Object a = *ptr; 解除引用会导致一份副本(正如我所预期的那样),但是通过Object &a = *ptr;解除引用不会导致一份副本吗?有趣。 - Mr. Smith
3
@Mr.Smith: 没错。ptr 是一个指向对象的指针,*ptr 是所指向的对象。在这一点上,没有人需要复制。将 *ptr 赋值给另一个对象 (Object a) 需要进行复制。引用原始对象(通过Object &a)则不需要复制。 - DevSolar
1
@Mr.Smith:我刚意识到我上面的评论可能措辞不当。将*ptr分配给另一个对象需要进行复制,因为之后你会有两个对象。引用原始对象不需要复制,因为你仍然只有那一个对象。(这也是为什么解引用指针本身并不昂贵的原因。) - DevSolar

1

通过引用传递对象只会传递指针,所以foo(*ptr)是正确的,不会复制对象。为什么要解引用它?因为函数签名想要一个对象,而不是一个对象的指针。C++是一种强类型语言。


C++ 不是强类型语言 - 实际上它根本不是;但它是静态的,你搞混了。 - phaazon
C++ 是 静态 的,请深深铭记在你们的脑海中。去学习 Haskell、Caml 或 F#,然后带着一个 正确的 定义回来。 - phaazon
嗯...对于“强类型”的定义和编译器设置来说,它是强类型的:) 总之,这与问题无关。 - TheMathemagician
1
@skp 隐式转换的存在并不一定意味着一种语言不是强类型的。你似乎在以原教旨主义的方式使用强弱类型术语。这里有一个关于强类型和弱类型的优点讨论,Guido van Rossum 和所有人都认为 C/C++/Java 都是强类型的。http://www.artima.com/intv/strongweakP.html - TheMathemagician
@skp C++是强类型语言,因为你可以对自定义类型进行强类型检查。它只在内置类型和从C继承的转换方面是弱类型的。该子集语言是弱类型的。其他所有内容都只有在你(程序员)将隐式转换放入类型定义中时才会变得弱类型。 - Konrad Rudolph
显示剩余4条评论

0

引用和指针是相同的。但是引用有自己的优势,那就是它们不能为 null(虽然它们可以,但很难使引用为空)。因此,您可以省略对 nullptr 的检查。您可以使用 . 而不是 ->,这样会少一个字符 xD。关于您的问题,由于指针和引用最终是相同的,选择其中一个不会有任何收益。我的意思是,下面的代码在编译时是相同的。

void foo(int &r) {}

并且

void foo(int *p) {}

当你使用引用时,后台将进行解除引用操作。 希望对您有所帮助。


指针和引用在编译后最终是相同的,至少在大多数已知的实现中是如此。标准并不要求这样。虽然可能不太可能,但某些平台可能会以不同的方式实现它们,在这种情况下,选择其中一个不一定不会带来任何收益,因此这种说法可能是错误的。关于实现定义的行为,请勿发表此类声明。 - underscore_d

0

若要将引用传递给函数,您必须像在值语义中一样传递对象。指针不是引用,因为它们是实体语义(地址)。

如果您取消引用指针,则会获得一个实际值,该值可以嵌入作为引用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接