【问题标题】:Dereference operator in C++C++ 中的取消引用运算符
【发布时间】:2016-10-16 10:15:42
【问题描述】:

我无法理解尊重运算符接受哪种类型的 value 作为其参数。 value,这里的意思是lvalue还是rvalue

考虑以下代码sn-p:

int i = 1, *p = &i;
cout << *p++; // Prints 1, so far so good.

现在,由于后缀 ++ 返回 p未增量值(与返回 增量对象 的前缀对应物不同),从上面的代码看来,一元* 接受右值作为其唯一的操作数。但是,

cout << *i;  // error: invalid type argument of unary ‘*’ (have ‘int’)

好的,i 的值可能不代表有效的内存地址。现在为了确认一元 * 可以处理代表有效内存位置的右值,我尝试了这样的事情:

unsigned long add = p;  // error: invalid conversion from ‘int*’ to ‘long unsigned int’ [-fpermissive]
cout << *add;           // error: invalid type argument of unary ‘*’ (have ‘int’)

这也让我想到了下一个问题。假设 unsigned long 的大小是 64 位(对于我正在处理的系统恰好是这样),为什么无法复制存储在 p 中的 value (发生这种情况是一个 64 位内存地址)到add?或者换句话说,有没有办法将内存地址存储在非指针类型的变量中(如果这是不可能的,我会感到惊讶,因为内存地址毕竟也是一个值)?

谢谢

【问题讨论】:

  • * 只能用于指针。您的代码 *i*add 失败,因为 iadd 是整数,而不是指针;与价值类别无关
  • 别再考虑位数了。 intdouble 可能都是 123 位长,但类型不同。 intunsigned int 可能各为 62 位,但类型不同。指针和整数是不同的类型,即使它们的位数可能相同。在绝大多数情况下,您不需要将指针转换为整数,反之亦然;这是一种可怕的代码气味。

标签: c++ pointers dereference


【解决方案1】:

内置的解引用运算符采用纯右值,必须是指针类型。如果操作数是glvalue,则在取消引用之前将对其进行左值到右值的转换。

如果你想在数据指针类型和等效大小的整数类型之间进行转换,你可以,但你必须说这就是你想要使用reinterpret_cast 做的事情。这是为了防止错误,例如忘记取消引用指向 int 的指针。

【讨论】:

  • 标准中的哪里规定内置解引用运算符采用纯右值? 5.3.1 中的第一段说它需要指向对象的指针或指向函数的指针。它没有指定值类别。我也可以在 xvalue 上使用它:ideone.com/GT2Qm9
  • @PcAF 参见 [conv.lval]/1。在需要prvalue的上下文中(例如*的操作数),glvalue可以转换为prvalue
  • 关于 xvalue,我的错,我认为左值到右值的转换适用于左值而不是左值。但问题仍然存在。你在读哪个文件?在n4594 [conv.lval]/1 中没有这样的句子。
  • @PcAF [expr]/9: “当一个泛左值表达式作为一个操作数的操作数出现时,该操作数需要一个纯右值,[...] 标准转换被应用来将表达式转换为prvalue。”该标准似乎没有说明何时需要prvalue。这可能是一个缺陷。
【解决方案2】:

如果没有显式转换(reinterpret_cast 或 C 样式转换),您无法将指针类型转换为非指针类型。或者该类应该具有隐式转换运算符。假设 intlong 将适合指针类型是错误且冒险的假设。如果您冒这个险,是的,您可以将指针存储为非指针类型:

int main()
{    
    int a, b;
    a = 10;
    b = (int)&a;

    a = 40;
    cout << *(int*)b << endl;

    *(reinterpret_cast<int*>(b)) = 160;
    cout << a << endl;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-12
    • 2015-08-17
    • 1970-01-01
    • 2021-01-23
    • 2018-08-04
    • 2019-09-22
    • 1970-01-01
    相关资源
    最近更新 更多