【问题标题】:Why is it required to return a reference from overloading bracket operators (OR: why is an lvalue not returned otherwise)?为什么需要从重载括号运算符返回引用(或者:为什么不返回左值)?
【发布时间】:2013-04-26 02:26:27
【问题描述】:

我已经尝试为一个类重载括号运算符,以减少访问数组的繁琐。我不明白的是,为什么必须将重载函数的返回类型声明为引用?为什么一开始就不是左值?

struct particle
{
    double v_x;
} 

struct particleSwarm
{
    int numParticles;
    particle* particles;
    particle operator[](int i) { return particles[i]; }
}

它返回一个particle 结构,为什么这无效,除非我让操作符返回一个引用:

void foo(particleSwarm& swarm)
{
    swarm[0].v_x = 5.0;
}

我不明白的是,为什么重载的函数没有返回左值?当试图弄清楚时,我发现这样的事情是有效的:

int* foo(particleSwarm* swarm)
{
    return &(swarm->numParticles);
}

void bar(particleSwarm* swarm)
{
    *(foo(swarm)) = 5;
}

为什么 foo 返回的指针是可以解引用和赋值的有效左值,而不是重载返回的对象?我知道如果我直接分配给它会怎么样,因为我没有重载=,但是我分配给它的一个成员变量,这似乎应该是有效的?我只是很难理解,所以我感谢任何花时间提供帮助的人!

【问题讨论】:

  • 它不是左值,因为您告诉它进行复制。默认情况下它不是任何东西。 foo 返回的指针不是一个有效的左值,它是一个右值。但是,当您取消引用指针时,that 的结果是一个左值。
  • 对返回引用的函数的函数调用表达式is lvalue
  • 我不确定我告诉它在哪里制作副本? return particles[i] 是否复制?由于取消引用指针会产生一个左值,调用成员变量不会使另一个成为左值吗?除非它当然是复制的,但我不明白为什么它是复制的 =/ 编辑:考虑一下,我可能明白为什么它是复制?如果是返回副本,为什么声明为particle& operator[](int i){return particles[i]}; 不返回副本?

标签: c++ operator-overloading lvalue square-bracket


【解决方案1】:

你的代码

void foo(particleSwarm& swarm)
{
    swarm[0].v_x = 5.0;
}

会被编译成类似的东西

void foo(particleSwarm& swarm)
{
    particle tmp = swarm.operator[](0);
    tmp.v_x = 5.0;
    // destruct tmp
}

【讨论】:

  • 为什么?这就是我不明白的。我没有看到从我的代码到此的连接。
  • 因为你的 operator[] 返回一个值而不是一个引用。返回值意味着您不想更改原始值并且想要原始值的副本。
  • 为什么即使您没有更改代码中的实际返回值,也可以将返回类型作为参考?我不是怀疑你,只是想了解更多=D
  • 引用是指针的语法糖。因此,您可以通过指针更改原始对象。
  • 所以,即使我没有更改函数内部实际返回的内容,只是函数声称返回的内容,它不再复制,而是返回对实际结构的引用?似乎,如果它一开始就制作副本,则引用将是对副本的引用,这没有任何好处……显然不是这样,但是……
猜你喜欢
  • 1970-01-01
  • 2012-04-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-08
  • 2012-02-22
相关资源
最近更新 更多