Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > operator[] -- returning references

Reply
Thread Tools

operator[] -- returning references

 
 
cppaddict
Guest
Posts: n/a
 
      06-11-2004
Hi,

Is it considered bad form to have the subscript operator return a
const reference variable? If not, what is the proper way to do it?
My question was prompted by the code below, my problematic attempt to
implement a subscript operator that returns a const reference. The
dubious code is marked at the end.

<code>

//MyClass is a large class we don't want to copy alot
//MyClass has a "char getChar()" function
class MyClass;

class SubscriptTest {
private:
std::vector<MyClass> _vect;
public:
SubscriptTest() {};
void addObj(MyClass mc) {_vect.push_back(mc);}
const MyClass& operator[] (char ch) const {return
lookUpByChar(ch);}
};

const MyClass& SubscriptTest::lookUpByChar(char ch) const {
for (unsigned i=0; i<_vect.size(); i++) {
if (_vect[i].getChar() == ch)
return i;
}

//PROBLEM IS HERE
return *(new MyClass); //return value here needed to compile
}

</code>

The problem is what to return when the lookup fails. Creating a
default value via new, as I do above, seems wrong -- it wastes memory
and requires tracking the objects created and then destroying them in
Subscript's destructor.

Another option would be to create the default value as static variable
inside the lookUpByChar function or as a member variable of
SubscriptTest, and have the function always return a reference to
that. That seems reasonable to me, but I still wasn't sure.

Does anyone have any thoughts/suggestions?

Thanks,
cpp

 
Reply With Quote
 
 
 
 
Rolf Magnus
Guest
Posts: n/a
 
      06-11-2004
cppaddict wrote:

> Hi,
>
> Is it considered bad form to have the subscript operator return a
> const reference variable?


No, not for the const version of it. It's actually the preferred way.

> If not, what is the proper way to do it?
> My question was prompted by the code below, my problematic attempt to
> implement a subscript operator that returns a const reference. The
> dubious code is marked at the end.
>
> <code>
>
> //MyClass is a large class we don't want to copy alot
> //MyClass has a "char getChar()" function
> class MyClass;
>
> class SubscriptTest {
> private:
> std::vector<MyClass> _vect;
> public:
> SubscriptTest() {};
> void addObj(MyClass mc) {_vect.push_back(mc);}
> const MyClass& operator[] (char ch) const {return
> lookUpByChar(ch);}
> };
>
> const MyClass& SubscriptTest::lookUpByChar(char ch) const {
> for (unsigned i=0; i<_vect.size(); i++) {
> if (_vect[i].getChar() == ch)
> return i;
> }
>
> //PROBLEM IS HERE
> return *(new MyClass); //return value here needed to compile
> }
>
> </code>
>
> The problem is what to return when the lookup fails. Creating a
> default value via new, as I do above, seems wrong -- it wastes memory
> and requires tracking the objects created and then destroying them in
> Subscript's destructor.
>
> Another option would be to create the default value as static variable
> inside the lookUpByChar function or as a member variable of
> SubscriptTest, and have the function always return a reference to
> that. That seems reasonable to me, but I still wasn't sure.
>
> Does anyone have any thoughts/suggestions?


Throw an exception.

 
Reply With Quote
 
 
 
 
cppaddict
Guest
Posts: n/a
 
      06-11-2004

>> Does anyone have any thoughts/suggestions?

>
>Throw an exception.


Rolf,

Doesn't the compiler require a return statement no matter what? It
seems to for me. Am I missing something?

Thanks,
cpp

 
Reply With Quote
 
Rolf Magnus
Guest
Posts: n/a
 
      06-11-2004
cppaddict wrote:

>
>>> Does anyone have any thoughts/suggestions?

>>
>>Throw an exception.

>
> Rolf,
>
> Doesn't the compiler require a return statement no matter what?


Not if that code path can't be reached anyway. Actually, my compiler.
You could just write:

const MyClass& SubscriptTest::lookUpByChar(char ch) const {
********for (unsigned i=0; i<_vect.size(); i++) {
****************if (_vect[i].getChar() == ch)
************************return i;
********}
********
throw SomeException("character not found");
********return MyClass(); //shut the compiler up
}

Yes, this would mean reuturning a reference to a temporary, but since
it's never actually reached, it doesn't hurt.

 
Reply With Quote
 
Rolf Magnus
Guest
Posts: n/a
 
      06-11-2004
Rolf Magnus wrote:

> Not if that code path can't be reached anyway. Actually, my compiler.


Insert "gives a warning if there is a return statement that can never be
reached" at a place of your choice.

 
Reply With Quote
 
Daniel T.
Guest
Posts: n/a
 
      06-11-2004
In article <>,
cppaddict <> wrote:

>Hi,
>
>Is it considered bad form to have the subscript operator return a
>const reference variable? If not, what is the proper way to do it?
>My question was prompted by the code below, my problematic attempt to
>implement a subscript operator that returns a const reference. The
>dubious code is marked at the end.
>
><code>
>
>//MyClass is a large class we don't want to copy alot
>//MyClass has a "char getChar()" function
>class MyClass;
>
>class SubscriptTest {
> private:
> std::vector<MyClass> _vect;
> public:
> SubscriptTest() {};
> void addObj(MyClass mc) {_vect.push_back(mc);}
> const MyClass& operator[] (char ch) const {return
>lookUpByChar(ch);}
>};
>
>const MyClass& SubscriptTest::lookUpByChar(char ch) const {
> for (unsigned i=0; i<_vect.size(); i++) {
> if (_vect[i].getChar() == ch)
> return i;
> }
>
> //PROBLEM IS HERE
> return *(new MyClass); //return value here needed to compile
>}
>
></code>
>
>The problem is what to return when the lookup fails. Creating a
>default value via new, as I do above, seems wrong -- it wastes memory
>and requires tracking the objects created and then destroying them in
>Subscript's destructor.
>
>Another option would be to create the default value as static variable
>inside the lookUpByChar function or as a member variable of
>SubscriptTest, and have the function always return a reference to
>that. That seems reasonable to me, but I still wasn't sure.
>
>Does anyone have any thoughts/suggestions?


The const version and the non-const version of op[] should do the same
thing if the item isn't in the container.

You have a few choices, declare the behavior undefined (thats how op[]
is defined in vector,) insert an element (the way op[] works in map,) or
throw an exception (like vector::at does.)

What is best for the code that uses your container?
 
Reply With Quote
 
AngleWyrm
Guest
Posts: n/a
 
      06-11-2004
"Rolf Magnus" <> wrote in message
news:cac1un$jgs$02$...

> throw SomeException("character not found");
> return MyClass(); //shut the compiler up
> }


> Yes, this would mean reuturning a reference to a temporary, but

since
> it's never actually reached, it doesn't hurt.


Isn't there a #pragma to disable specific warnings for one or more
instances/lines? I've never used pragma, but this might be a good
place for it, if that's how it's used.


 
Reply With Quote
 
Maxim Yegorushkin
Guest
Posts: n/a
 
      06-11-2004
Rolf Magnus wrote:

> cppaddict wrote:
>
>> Hi,
>>
>> Is it considered bad form to have the subscript operator return a
>> const reference variable?

>
> No, not for the const version of it. It's actually the preferred way.


This is rather arguable and senseless outside a context.

There is a rule of thumb: when in doubt do what built-in types do. Consider the operator[]'s behavior applied to a pointer - it always returns a pointee type reference, no matter whether the pointer itself is cv-qualified or not.

char c(0);
char* p1 = &c; // non-const pointer, non-const pointee
char* const p2 = &c; // const pointer, non-const pointee

char& r1 = *p1;
char& r2 = *p2;

--
Maxim Yegorushkin
 
Reply With Quote
 
cppaddict
Guest
Posts: n/a
 
      06-11-2004
>The const version and the non-const version of op[] should do the same
>thing if the item isn't in the container.


In my case, wouldn't it violate encapsulation to have a non-const
version? Essentially, that would be returning a refernece to private
data.

>You have a few choices, declare the behavior undefined (thats how op[]
>is defined in vector,)


How do you declare behaviour as undefined?

Thanks,
cpp

 
Reply With Quote
 
cppaddict
Guest
Posts: n/a
 
      06-11-2004
>This is rather arguable and senseless outside a context.
>
>There is a rule of thumb: when in doubt do what built-in types do. Consider the operator[]'s behavior applied to a pointer - it always returns a pointee type reference, no matter whether the pointer itself is cv-qualified or not.
>
>char c(0);
>char* p1 = &c; // non-const pointer, non-const pointee
>char* const p2 = &c; // const pointer, non-const pointee
>
>char& r1 = *p1;
>char& r2 = *p2;


Maxim,

It's not clear to me what point you are trying to make or what advice
you are trying to give with this example. Could you please explain?

Thanks,
cpp

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Snake references just as ok as Monty Python jokes/references in python community? :) seberino@spawar.navy.mil Python 8 12-12-2006 11:21 PM
Typedef A references struct B which references struct A which... DanielEKFA C++ 8 05-16-2005 10:26 AM
Difference between bin and obj directories and difference between project references and dll references jakk ASP .Net 4 03-22-2005 09:23 PM
how to understand references to variables and references to constants are distinguished? baumann.Pan@gmail.com C++ 3 11-10-2004 04:16 AM
Pointers and References (and References to Pointers) Roger Leigh C++ 8 11-17-2003 10:14 AM



Advertisments