【问题标题】:How to get a pointer from a reference?如何从引用中获取指针?
【发布时间】:2012-02-13 16:00:35
【问题描述】:

似乎有很多关于指针与引用的相关问题,但我找不到我想知道的。基本上,对象是通过引用传入的:

funcA(MyObject &objRef) { ... }

在函数中,我可以获取指向该对象的指针而不是引用吗?如果我将引用objRef 视为MyObject 的别名,&objRef 实际上会给我一个指向MyObject 的指针吗?似乎不太可能。我很困惑。

编辑:经过仔细检查,objRef 确实给了我指向我需要的对象的指针 - 你们中的大多数人给了我正确的信息/答案,非常感谢。在这种情况下,我选择了似乎最能说明问题的答案。

【问题讨论】:

  • 为什么需要引用中的指针?
  • @Griwes:在我的脑海中,可能需要指针数学,或者其他 API 可能需要指针。
  • 如果你只是得到参考的地址呢? &objRef
  • @DrewDormann,什么,通过引用传递的对象地址的指针数学?在我看来这不是好的设计。
  • 例如传入引用,解析reinterpret_cast<char *>等二进制流需要指针类型。

标签: c++


【解决方案1】:

是的,将地址运算符应用于引用与获取原始对象的地址相同。

#include <iostream>

struct foo {};

void bar( const foo& obj )
{
  std::cout << &obj << std::endl;
}

int main()
{
  foo obj;
  std::cout << &obj << std::endl;
  bar( obj );

  return 0;
}

结果:

0x22ff1f
0x22ff1f

【讨论】:

  • 这不是“参考地址”。是的,引用可能会占用内存空间,因此有一个地址,但没有类型安全的方法可以找到它。
【解决方案2】:

应用于引用的任何运算符实际上将应用于它所引用的对象(§5/5 [expr]);可以将引用视为同一对象的另一个名称。因此,获取引用的地址将为您提供它所引用的对象的地址。

实际上未指定引用是否需要存储(§8.3.2/4 [dcl.ref]),因此获取引用本身的地址是没有意义的.

举个例子:

int x = 5;
int& y = x;
int* xp = &x;
int* yp = &y;

在上面的示例中,xpyp 相等 - 即表达式 xp == yp 的计算结果为 true,因为它们都指向同一个对象。

【讨论】:

  • 引用不仅仅是同一个对象的另一个名称(引用的生命周期不同于它指向的对象的生命周期)。但是,您的示例代码将起作用,因为在引用上使用任何运算符实际上会使用目标对象。
  • @BenVoigt:调用析构函数后,对象被销毁。它不再存在。因此,您试图使用未定义的行为来证明您的断言是正确的。都毫无意义。我没有问题。我只是在第一条评论中因您的错误陈述而大声疾呼。引用只不过是一个别名。您描述的所有影响都只是未定义行为或实现副作用的结果。
  • @Ben:是的,我总是发现单方面的论点(博客)是了解真相的最佳方式。您自己说过,引用是别名。别名 => '另一个名字'。是的。完全合法的代码仍然会导致未定义的行为。我所说的是有效代码(即不调用未定义的行为),引用不会比它引用的对象持续更长时间,并且充当对象的另一个名称。你是说:当我们调用未定义的行为时,引用的行为就像一个指针。我说是的,那又怎样。
  • @Loki:我将在完全相同的位置用另一个int 替换int,那里没有问题。显然它是一个新对象(析构函数在旧对象上运行,构造函数在新对象上运行)。该标准还说它是一个新对象。我看不出您对此新发现的方法(替换现在已被击败的未定义行为的主张)根本没有任何意义,因为它完全消除了术语“对象生命周期”的任何含义。似乎更像是一种绝望的尝试,为您对我的评论和示例的一再攻击辩解。
  • @Loki:新对象是int,每行第 44 行。您只是在证明您既没有阅读也没有理解我的示例。甚至根本不需要一个新对象。阅读同一部分的第 6 段。 C++ 引用绑定到内存位置,而不是对象。就像一个指针。标准的措辞支持这一点,您没有任何相反的证据。
【解决方案3】:

一般的解决方法是使用std::addressof,如:

#include <type_traits>

void foo(T & x)
{
    T * p = std::addressof(x);
}

无论T 是否重载operator&amp;,这都有效。

【讨论】:

  • 好点,因为引用被引用的对象,如果该对象可能重载operator &amp;,需要小心。 . 有一天我会在我需要的地方恢复那个项目!
【解决方案4】:

在引用上使用地址 (&amp;) 运算符。

&objRef

就像在引用上使用的任何其他运算符一样,这​​实际上会影响被引用的对象。

正如@Kerrek 指出的那样,由于运算符会影响引用的对象,如果该对象具有重载的operator&amp; 函数,则会调用它,并且需要std::address_of 来获取真实地址。

【讨论】:

    【解决方案5】:

    在引用上使用地址运算符。

    MyObject *ptr = &objRef;
    

    【讨论】:

    • 这没有得到“引用的地址”。
    • @BenVoigt:“Use the address operator on the reference”会更准确吗?我知道你不喜欢我的术语,但我想确定原因。
    【解决方案6】:

    在 C++ 中,引用是一种受限类型的指针。它只能分配一次,并且永远不能有 NULL 值。 当用于指示函数的参数是通过引用传递变量的地址时,引用最有用。如果没有引用,则使用按值传递。

    【讨论】:

    • 没有。引用是现有对象的别名。当你开始做更复杂的事情时,把它当作一个花哨的指针只会让你感到困惑。
    • @Loki:引用是句柄。指针也是如此。它们都消耗存储空间(除非经过优化),并且与引用的对象具有不同的生命周期。相似之处远大于差异。
    • @BenVoigt:注意术​​语。句柄在 comp sci 中还有其他含义。但我同意你的观点。但我不同意你的意见。另请注意 8.3.2 引用 [dcl.ref] 第 4 段 未指定引用是否需要存储 如果引用就像一个指针,为什么我不能获得对我的引用的引用(它因为它不存在)。它只是一个别名。
    • @damson:是的,网络上有很多废话参考。在此处获取标准副本:stackoverflow.com/a/4653479/14065
    • 看看这个:reference 知道什么是引用的行为,而这个:pointers 因为你不知道什么是指针。
    猜你喜欢
    • 1970-01-01
    • 2021-01-07
    • 2016-09-03
    • 2020-06-14
    • 1970-01-01
    • 2021-08-03
    • 1970-01-01
    • 2021-04-11
    • 1970-01-01
    相关资源
    最近更新 更多