views:

141

answers:

3

Problem with operator[] in c++, i have some class:

197 class Permutation{
198         private:
199                 unsigned int* array;
200                 unsigned int size;
201
202                 void fill(){
203                         for(unsigned int i=0;i<size;i++)
204                                 array[i]=i;
205                 }
206                 void init(const unsigned int s){
207                         if(s){
208                                 array=new unsigned int[s];
209                                 size=s;
210                         }else{
211                                 size=0;
212                                 array=0;
213                         }
214                 }
215                 void clear(){
216                         if(array){
217                                 delete[]array;
218                                 array=0;
219                         }
220                         size=0;
221                 }
222         public:
223                 Permutation(const unsigned int& s=0):array(0),size(0){
224                         init(s);
225                         fill();
226                 }
227                 ~Permutation(){
228                         clear();
229                 }
230                 unsigned int& operator[](const unsigned int& idx){
231                         assert(idx<size);
232                         return array[idx];
233                 }
234                 unsigned int& get(const unsigned int& idx)
235                 {
236                         assert(idx<size);
237                         return array[idx];
238                 }


253                 Permutation& operator=(const Permutation& p){
254                         clear();
255                         init(p.size);
256                         size=p.size;
257                         for(unsigned int i=0;i<size;i++)
258                                 array[i]=p.array[i];
259                         return *this;
260                 }
261
262                 Permutation(const Permutation&p)
263                 {
264                         clear();
265                         init(p.size);
266                         size=p.size;
267                         for(unsigned int i=0;i<size;i++)
268                                 array[i]=p.array[i];
269                 }
};

when I use

Permutation x(3);
x[0]=1;

it works very well, but when I use:

Permutation* x=new Permutation(3);
x->get(0)=10; // this works fine
x[0]=1;

in this case, in debugger I see it is called a constructor of new object for Permutation class, what is going on ? and why? I someone know what is going about I would appreciate for information.

+6  A: 

First, your code:

Permutation* x=new Permutation(3);
x->get(0)=10; // this works fine

And then you do this:

x[0]=1;

And what you are doing is treating the pointer x as an array, and initializing it, which is longhand for:

x[0] = Permuation(1);  // implicit conversion using Permulation(const unsigned long&)

What you meant to write was:

(*x)[0]=1;  // follow x and then invoke the [] operator

Or, equivalent:

x->operator[](0) = 1;
Will
Thank you for answer! It is more elegant way to call (*x)[0]=1, or it is the prettiest?
Tomek
@Tomek: added an alternative form; no opinion on the relative prettiness of the two options though :)
Will
http://www.gotw.ca/publications/c_family_interview.htm In an interview, Stroustrup says that he considered adding a syntax like `x->[0]` to the language, but it didn't make it.
ephemient
+2  A: 

For pointers, x[0] is equivalent to *(x+0), which is equivalent to *x. So you're actually assigning to the Permutation object.

Since you're assigning a value 1, the Permutation(const unsigned int&) conversion constructor is used. This creates a temporary of type Permutation, which is then copies into the object *x, using your assignment operator.

avakar
A: 

I wanted to present one other option on how you can write this a bit easier. Instead of working with the pointer, you can create a reference:

Permutation &rx = *x;
rx[0] = 1;  // same as (*x)[0] = 1;

If you are using an overloaded operator in just one place, this is overkill. But I find this trick quite convenient when you are using overloaded operators in many places.

R Samuel Klatchko
thx. Very tricky :)
Tomek