0

I have a following class foo

class foo
{
    int *arr; // arr holds numbers
    int sz; // size of array
    public:
    // Suppose I have made default and 1 parameter c'tor
    foo(const foo &f)
    {
        sz = f.sz;
        arr = new int[sz];
        for(int i=0;i<sz;i++)
            arr[i]=f.arr[i];
    }
};

int main()
{
    foo x(5); //5 is size of array
    const foo y = x; //doesn't work as I haven't initialized in member-initialization list, but how to write for loop in member initialization list ?
}  

So How do I write for loop in member initialization list ?

Happy Mittal
  • 3,667
  • 12
  • 44
  • 60
  • 1
    Your line `foo x(5);` won't compile with the code you've shown, there is no constructor with an `int` parameter. Does your comment about "1 parameter c'tor" refer to an `foo(int)` constructor that does exist in your real code? I read it as applying to the copy ctor. –  Oct 18 '12 at 08:01
  • 1
    What do you mean "it doesn't work"? If you provide a constructor `explicit foo(int)` it compiles. – juanchopanza Oct 18 '12 at 08:04
  • I have already created parameterized c'tor although I haven't written them here. Assume they exist. – Happy Mittal Oct 18 '12 at 08:05
  • 2
    "doesn't work". How doesn't it work; what error message do you get? – CB Bailey Oct 18 '12 at 08:05
  • @juanchopanza: I gives compiler error – Happy Mittal Oct 18 '12 at 08:05
  • @Roddy: passing 'const foo' as 'this' argument of 'T& foo::operator[](unsigned int)' discards qualifiers [-fpermissive] – Happy Mittal Oct 18 '12 at 08:08
  • Actually, **please forget the _possible duplicate_ suggestion above.** The difference is that in this question here, the array is dynamically allocated. – jogojapan Oct 18 '12 at 08:09
  • 3
    @HappyMittal The error you describe has nothing to do with the copy constructor. It has to do with the fact that `operator[]`, which apparently you also define for your class, is not a `const`-method. – jogojapan Oct 18 '12 at 08:16
  • There is no `foo::operator[]` in your code, how can the error message mention it? Are you sure your copy ctor is exactly as written in the question? – Gorpik Oct 18 '12 at 08:19
  • Can you update your code to be a minimal example that shows the problem? The error message doesn't correspond to the code you're showing us. – Roddy Oct 18 '12 at 08:22

3 Answers3

3

You could just use a std::vector in this case… anyways.

Typically, I will create a private static method which will perform the allocation and copy. Then the initialization list may be used:

static int* CloneInts(const foo& f) {
    int* ints = new ...
    ...copy them from @a f.arr...
    return ints;
}

Then your init-list would look like:

foo(const foo& f) : arr(CloneInts(f)), sz(f.sz) {
justin
  • 104,054
  • 14
  • 179
  • 226
  • Actually I am trying to mimic std::vector, not using it :D Can you please tell how static method can be used in initializer list ? I didn't get you. – Happy Mittal Oct 18 '12 at 08:04
3

Have you tried constructing it with the copy constructor directly?

const foo y(x);

jvstech
  • 844
  • 1
  • 9
  • 28
  • No. It will run the exact code you have in your copy constructor. It will allocate a new `int` array and copy the values from the source `foo` to it. – jvstech Oct 18 '12 at 08:08
  • Then why do we need copy c'tor ? I thought the reason we need copy c'tor is because compiler does bit by bit copy. – Happy Mittal Oct 18 '12 at 08:12
  • You implement your own copy constructor to override the code the compiler generates. – jvstech Oct 18 '12 at 08:13
  • Some confusion here: In the absense of a copy constructor, the compiler does generate its own. But, that would just copy the pointer rather than realloc the array. jvstech's suggestion is to avoid any possibility that the compiler is invoking the default constructor, followed by the assignment operator. – Roddy Oct 18 '12 at 08:26
2

You should clarify your problem, because the one in the question doesn't actually exist.

The const foo y = x; line will compile and work with that copy constructor. A const object under construction isn't "const' until the constructor has completed. So the constructor body is permitted to modify the object even if the object being constructed is const.

Also note that the loop in the example isn't even modifying anything that's ever const - since the array is allocated dynamically, those array elements are modifiable even if the object itself isn't. For example, the arr pointer isn't modifiable after the ctor has completed, but arr[0] still is.

Try out the following to see both points in action:

#include <stdio.h>
#include <algorithm>

class foo
{
    int *arr; // arr holds numbers
    int sz; // size of array
    public:
    foo() : arr(0), sz(0) { puts("default ctor");}
    foo(int x) : arr(0), sz(x) {
        puts( "int ctor");
        arr = new int[sz];
        for(int i=0;i<sz;i++)
            arr[i]=0;
    }

    foo(const foo &f)
    {
        puts("copy ctor");
        sz = f.sz;
        arr = new int[sz];
        for(int i=0;i<sz;i++)
            arr[i]=f.arr[i];
    }

    ~foo() {
        delete [] arr;
    }

    foo& operator=(const foo& rhs) {
        if (this != &rhs) {
            foo tmp(rhs);
            std::swap( arr, tmp.arr);
            std::swap( sz, tmp.sz);
        }

        return *this;        
    }

    void update() const {
        for(int i = 0; i < sz; i++) {
            arr[i] = arr[i] + 1;
        }
    }

    void dump() const {
        for(int i = 0; i < sz; i++) {
            printf("%d ", arr[i]);
        }
        puts("");
    }
};

int main()
{
    foo x(5); //5 is size of array
    const foo y = x; 

    y.dump();
    y.update(); // can still modify the int array, even though `y` is const
    y.dump();
}  

I think you may be confusing constructing const objects with constructing objects that have const members since those members must be initialized in the initialization list.

Michael Burr
  • 333,147
  • 50
  • 533
  • 760