By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
454,445 Members | 1,329 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 454,445 IT Pros & Developers. It's quick & easy.

index operator[] overloading

P: n/a
Can anyone explain how this works. How may I implement this?

I want to be able to use the operator on both lhs and rhs of assignment
statements. The rhs is a no-brainer (at least I think I got it right):

class MyArray
{
public:
MyArray(const size_t size):m_size(size){ arr_ = new double[size]; }
~MyArray(){ if (arr_) delete[] arr_ ;}

double operator[](const size_t idx)
{ if (idx < m_size)
return arr_[idx];
throw std::exception
}

private:
MyArray(const MyArray&);
operator= (const MyArray&);

double *arr_ ;
size_t m_size ;
}
I read somewhere that the type returned from the [] operator must be a
reference, but I did not quite follow the reasoning/logic - anyone care
to explain ?
May 29 '07 #1
Share this Question
Share on Google+
15 Replies


P: n/a
Bart Simpson wrote:
>
I read somewhere that the type returned from the [] operator must be a
reference, but I did not quite follow the reasoning/logic - anyone care
to explain ?
A reference is a variable that relates to another variable. for example

int x = 0;
int& y = x;
y = 1;

at the end, x will have a value of 1, because y refers to the same
memory location as x, so it's bind to the x value until the end of its
scope (that hopefully is before or at the same time as the x one :)

In your case it's exactly the same: if you return a reference, you are
returning a (temporary) variable that refers to the address of the
element that you want to modify. So, if you assign a value to this
variable (that would be prohibited if it wasn't a reference, because is
a temporary), the value will be written in the memory location of your
array element.

that's it!

Regards,

Zeppe
May 29 '07 #2

P: n/a
Thanks Zeppe that clarifies that.

So to implement it one has to implement BOTH of these?

myType operator[](const size_t) const;
myType& operator[](const size_t);
May 29 '07 #3

P: n/a
Bart Simpson wrote:
Thanks Zeppe that clarifies that.

So to implement it one has to implement BOTH of these?

myType operator[](const size_t) const;
myType& operator[](const size_t);
exactly, and the compiler will chose the proper one based on the
"const". Another hint: the method

myType operator[](const size_t) const;

makes a copy of the element that it returns, which can be undesirable if
the objects myType are big. So, it usually common to do

const myType& operator[](const size_t) const;
myType& operator[](const size_t);

if you return a const reference, you can't use it in the left side of
the assignment, and you avoid the copy on the return.

Regards,

Zeppe
May 29 '07 #4

P: n/a


Zeppe wrote:
Bart Simpson wrote:
>Thanks Zeppe that clarifies that.

So to implement it one has to implement BOTH of these?

myType operator[](const size_t) const;
myType& operator[](const size_t);


exactly, and the compiler will chose the proper one based on the
"const". Another hint: the method

myType operator[](const size_t) const;

makes a copy of the element that it returns, which can be undesirable if
the objects myType are big. So, it usually common to do

const myType& operator[](const size_t) const;
myType& operator[](const size_t);

if you return a const reference, you can't use it in the left side of
the assignment, and you avoid the copy on the return.

Regards,

Zeppe
Thanks!
May 29 '07 #5

P: n/a
On May 29, 7:30 pm, Zeppe
<zep_p@.remove.all.this.long.comment.yahoo.itwrote :
Bart Simpson wrote:
Thanks Zeppe that clarifies that.
So to implement it one has to implement BOTH of these?
myTypeoperator[](constsize_t)const;
myType&operator[](constsize_t);

exactly, and the compiler will chose the proper one based on the
"const". Another hint: the method
To the much of my surprise, I tried this and the non-constant version
is always called. Here is the code:

#include <iostream>

class MyArray
{
public:
MyArray(const size_t size) : m_size(size) {
arr_ = new double[size];
}

~MyArray() {
if (arr_) delete[] arr_ ;
}

double& operator[](const size_t idx)
{
std::cout << "LHS" << std::endl;
return arr_[idx];
}

const double& operator[](const size_t idx) const
{
std::cout << "RHS" << std::endl;
return arr_[idx];
}

double *arr_;
size_t m_size;
};

int main(int argc, char** argv) {
MyArray a(3);
a[0] = 8.0;
std::cout << a[0] << std::endl;
return 0;
}

The output in both cases is "LHS". What's wrong?

-Mustafa

May 29 '07 #6

P: n/a
Project X wrote:
On May 29, 7:30 pm, Zeppe
<zep_p@.remove.all.this.long.comment.yahoo.itwrote :
>Bart Simpson wrote:
>>Thanks Zeppe that clarifies that.
>>So to implement it one has to implement BOTH of these?
>>myTypeoperator[](constsize_t)const;
myType&operator[](constsize_t);

exactly, and the compiler will chose the proper one based on the
"const". Another hint: the method

To the much of my surprise, I tried this and the non-constant version
is always called. Here is the code:

#include <iostream>

class MyArray
{
public:
MyArray(const size_t size) : m_size(size) {
arr_ = new double[size];
}

~MyArray() {
if (arr_) delete[] arr_ ;
}

double& operator[](const size_t idx)
{
std::cout << "LHS" << std::endl;
return arr_[idx];
}

const double& operator[](const size_t idx) const
{
std::cout << "RHS" << std::endl;
return arr_[idx];
}

double *arr_;
size_t m_size;
};

int main(int argc, char** argv) {
MyArray a(3);
a[0] = 8.0;
std::cout << a[0] << std::endl;
return 0;
}

The output in both cases is "LHS". What's wrong?
Nothing. 'a' is declared non-const. Why would a const function
be called when non-const is available?

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
May 29 '07 #7

P: n/a
On 29 Maj, 21:03, Project X <elsheik...@gmail.comwrote:
On May 29, 7:30 pm, Zeppe

<zep_p@.remove.all.this.long.comment.yahoo.itwrote :
Bart Simpson wrote:
Thanks Zeppe that clarifies that.
So to implement it one has to implement BOTH of these?
>myTypeoperator[](constsize_t)const;
myType&operator[](constsize_t);
exactly, and the compiler will chose the proper one based on the
"const". Another hint: the method

To the much of my surprise, I tried this and the non-constant version
is always called. Here is the code:

#include <iostream>

class MyArray
{
public:
MyArray(const size_t size) : m_size(size) {
arr_ = new double[size];
}

~MyArray() {
if (arr_) delete[] arr_ ;
}

double& operator[](const size_t idx)
{
std::cout << "LHS" << std::endl;
return arr_[idx];
}

const double& operator[](const size_t idx) const
{
std::cout << "RHS" << std::endl;
return arr_[idx];
}

double *arr_;
size_t m_size;

};

int main(int argc, char** argv) {
MyArray a(3);
a[0] = 8.0;
std::cout << a[0] << std::endl;
return 0;

}

The output in both cases is "LHS". What's wrong?
Your program works fine. When the compiler chooses between operator[]
(const size_t idx) and operator[](const size_t idx) const, it makes
its determination based on whether the object in question is const or
not. Since your "a" is non-const, it will always choose the non-const
operator. Try e.g. adding this function and call it:

void f_const(MyArray const& a)
{
a[0];
}

then compare it with
void f_non_const(MyArray& a)
{
a[0];
}

/Peter

May 29 '07 #8

P: n/a
In article <NM*********************@bt.com>, 12**********@terrace.com
says...
Thanks Zeppe that clarifies that.

So to implement it one has to implement BOTH of these?

myType operator[](const size_t) const;
myType& operator[](const size_t);
You probably need a Proxy. See _More Effective C++_, Item 30.

--
Later,
Jerry.

The universe is a figment of its own imagination.
May 30 '07 #9

P: n/a
On Wed, 30 May 2007 06:51:09 -0600, Jerry Coffin wrote:
In article <NM*********************@bt.com>, 12**********@terrace.com
says...
>Thanks Zeppe that clarifies that.

So to implement it one has to implement BOTH of these?

myType operator[](const size_t) const; myType& operator[](const
size_t);

You probably need a Proxy.
Why?
See _More Effective C++_, Item 30.
Um... not everyone has that book...

--
Lionel B
May 30 '07 #10

P: n/a
On May 30, 9:58 am, Lionel B <m...@privacy.netwrote:
On Wed, 30 May 2007 06:51:09 -0600, Jerry Coffin wrote:
In article <NMKdnXsg9qWXzsHbRVny...@bt.com>, 123evergr...@terrace.com
says...
Thanks Zeppe that clarifies that.
So to implement it one has to implement BOTH of these?
myType operator[](const size_t) const; myType& operator[](const
size_t);
You probably need a Proxy.

Why?
See _More Effective C++_, Item 30.

Um... not everyone has that book...

--
Lionel B
Buy it now! It is cheap and worthy!

May 30 '07 #11

P: n/a
In article <f3**********@south.jnrs.ja.net>, me@privacy.net says...

[ ... ]
myType operator[](const size_t) const; myType& operator[](const
size_t);
You probably need a Proxy.

Why?
Because it works quite nicely in this situation, and attempts at doing
the job without a proxy won't.
See _More Effective C++_, Item 30.

Um... not everyone has that book...
If they want to deal with this subject, it's worth getting. Seriously,
that item starts on page 213 and ends up page 228. That's far too much
material to attempt to reproduce in a Usenet post -- especially since
(at least if memory serves) it contains references to other parts of the
book as well, so a standalone post would need to contain still more.

Almost anybody getting beyond the basics of C++ should get (probably all
of) Scott Meyers' books -- _Effective C++_ (currently in the third
edition, I believe) is definitely the best of them, but _More Effective
C++_ and _Effective STL_ are worth getting as well. Alternatively, the
_Effective C++ CD_ delivers essentially the same content as the first
two books in electronic form for a bit less money and a lot better
searching -- besides it lets you help support "a man with hair worthy of
Kevlin Henney" (sorry, that's a little bit of a reversed, inside joke,
but if Scott or Kevlin reads this, they'll probably laugh.)

--
Later,
Jerry.

The universe is a figment of its own imagination.
May 31 '07 #12

P: n/a
On 2007-05-30 17:34:39 -0700, Jerry Coffin <jc*****@taeus.comsaid:
In article <f3**********@south.jnrs.ja.net>, me@privacy.net says...

[ ... ]
>>>myType operator[](const size_t) const; myType& operator[](const
size_t);

You probably need a Proxy.

Why?

Because it works quite nicely in this situation, and attempts at doing
the job without a proxy won't.
Won't work in what way?
--
Clark S. Cox III
cl*******@gmail.com

May 31 '07 #13

P: n/a
In article <2007053114072116807-clarkcox3@gmailcom>, cl*******@gmail.com
says...

[ ... ]
Because it works quite nicely in this situation, and attempts at doing
the job without a proxy won't.

Won't work in what way?
Won't invoke the correct version of the operator (const vs. non-const)
in the right situation -- in particular, in the right side of an
assignment, you want the const operator called, and in the left side,
you want the non-const operator called. Overloading the operators
directly, the one that gets called is based on whether the object is
const or not -- for example, if it's not const, the non-const operator
is called even on the right side of the assignment.

--
Later,
Jerry.

The universe is a figment of its own imagination.
Jun 1 '07 #14

P: n/a
On Thu, 31 May 2007 22:28:35 -0600, Jerry Coffin wrote:
In article <2007053114072116807-clarkcox3@gmailcom>, cl*******@gmail.com
says...

[ ... ]
Because it works quite nicely in this situation, and attempts at
doing the job without a proxy won't.

Won't work in what way?

Won't invoke the correct version of the operator (const vs. non-const)
in the right situation -- in particular, in the right side of an
assignment, you want the const operator called, and in the left side,
you want the non-const operator called.
Do I? How do you know?
Overloading the operators
directly, the one that gets called is based on whether the object is
const or not -- for example, if it's not const, the non-const operator
is called even on the right side of the assignment.
But perhaps that's what I want... ok, most of the time I probably don't,
but you can't assume that.

--
Lionel B
Jun 4 '07 #15

P: n/a
In article <f4**********@south.jnrs.ja.net>, me@privacy.net says...
On Thu, 31 May 2007 22:28:35 -0600, Jerry Coffin wrote:
[ ... ]
Won't invoke the correct version of the operator (const vs. non-const)
in the right situation -- in particular, in the right side of an
assignment, you want the const operator called, and in the left side,
you want the non-const operator called.

Do I? How do you know?
The same way I know that you want your operator= to return *this, that
you don't want your destructors to throw exceptions, and so on.
Overloading the operators
directly, the one that gets called is based on whether the object is
const or not -- for example, if it's not const, the non-const operator
is called even on the right side of the assignment.

But perhaps that's what I want... ok, most of the time I probably don't,
but you can't assume that.
In point of fact, experience indicates that it's quite a safe
assumption. Yes, when people overload operator[] for completely
different purposes (e.g. Boost.spirit) it's sometimes reasonable to do
things entirely differently. When you're using it for subscripting,
however, this is an "assumption" about the same way it's an
"assumption" that the sun will rise tomorrow morning.

--
Later,
Jerry.

The universe is a figment of its own imagination.
Jun 4 '07 #16

This discussion thread is closed

Replies have been disabled for this discussion.