0

I've tried overloading the bracket operators for a class, to make accessing the array less tedious. What I don't understand is, why is it neccesary to declare the return type of the overload function as a reference? Why is it not an lvalue to begin with?

struct particle
{
    double v_x;
} 

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

It returns a particle struct, so why is this not valid, unless I make the operator return a reference:

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

What I don't understand is, why isn't the overloaded function already returning an lvalue? When trying to figure it out, I discovered that something like this is valid:

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

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

Why is the pointer returned by foo a valid lvalue that can be dereferenced and assigned to, but not the object returned by the overload? I see how it wouldn't be if I were assigning directly to it, since I haven't overloaded =, but I'm assigning to one of it's member variables, which it seems like should be valid? I'm just having a hard time understanding, so I appreciate anyone who takes the time to help!

Fulluphigh
  • 506
  • 1
  • 8
  • 21
  • 1
    It's not an lvalue because you told it to make a copy. It's not anything by default. The pointer returned by foo is not a valid lvalue, it's an rvalue. However, when you dereference the pointer the result of _that_ is an lvalue. – Mooing Duck Apr 26 '13 at 02:29
  • a function call expression to a function returning a reference *is* lvalue – Cubbi Apr 26 '13 at 02:31
  • I'm not sure where I told it to make a copy? Does `return particles[i]` make a copy? And as derefencing the pointer results in an lvalue, wouldn't calling for the member variable make the other an lvalue? Unless of course it's copied, but I don't understand why it's a copy =/ Edit: Thinking about it, I maybe understand why it's a copy? If it is returning a copy, why does declaring it as `particle& operator[](int i){return particles[i]};` not return a copy? – Fulluphigh Apr 26 '13 at 02:34

1 Answers1

1

Your code

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

will be compiled into something like

void foo(particleSwarm& swarm)
{
    particle tmp = swarm.operator[](0);
    tmp.v_x = 5.0;
    // destruct tmp
}
brian beuning
  • 2,836
  • 18
  • 22
  • Why? That's what I don't understand. I don't see the connection from my code to this. – Fulluphigh Apr 26 '13 at 05:23
  • Because your operator[] returns a value and not a reference. Returning a value means you do not want to change the original and you want a copy of the original value. – brian beuning Apr 26 '13 at 12:08
  • Why does having the return type as a reference make things okay, even when you don't change the actual return in the code? I'm not doubting you, just trying to learn more =D – Fulluphigh Apr 26 '13 at 20:44
  • A reference is syntactic sugar for a pointer. So you can change the original object thru the pointer. – brian beuning Apr 26 '13 at 22:42
  • So, even though I don't change what I actually return inside the function, just what the function claims it returns, it no longer makes a copy, but returns a reference to the actual struct? It seems as if, if it were making a copy to begin with, the reference would be to the copy, which wouldn't do any good... That's clearly not the case, but... – Fulluphigh Apr 27 '13 at 03:27