surprising constructors for a class!

Discussion in 'C++' started by Srinu, Aug 18, 2010.

  1. Srinu

    Srinu Guest

    Hi,

    What is the problem here in this code?
    It gives segmentation fault. I found value of size in vector (int *a)
    is no more 3. How is this?



    ==============
    #include <iostream>

    using namespace std;

    class vector
    {
    int *v;
    int size;
    public:
    vector(int m)
    {
    v = new int[size = m];
    for(int i=0; i<size; i++)
    v = 0;
    }
    vector (int *a)
    {
    for(int i=0; i<size; i++)
    v = a;
    }
    int operator*(vector &y)
    {
    int sum = 0;
    for(int i=0; i<size; i++)
    sum += this -> v * y . v;
    return sum;
    }
    };

    int main()
    {
    int x[3] = {1,2,3};
    int y[3] = {4,5,6};
    vector v1(3);
    vector v2(3);
    v1 = x;
    v2 = y;
    int R = v1 * v2;
    cout << "R = " << R;
    return 0;
    }

    Sincerely,
    Srinivas Nayak
     
    Srinu, Aug 18, 2010
    #1
    1. Advertising

  2. On 8/18/2010 1:49 PM, Srinu wrote:
    > ==============
    > #include<iostream>
    >
    > using namespace std;
    >
    > class vector
    > {
    > int *v;
    > int size;
    > public:
    > vector(int m)
    > {
    > v = new int[size = m];
    > for(int i=0; i<size; i++)
    > v = 0;
    > }
    > vector (int *a)
    > {
    > for(int i=0; i<size; i++)
    > v = a;
    > }
    > int operator*(vector&y)
    > {
    > int sum = 0;
    > for(int i=0; i<size; i++)
    > sum += this -> v * y . v;
    > return sum;
    > }
    > };
    >
    > int main()
    > {
    > int x[3] = {1,2,3};
    > int y[3] = {4,5,6};
    > vector v1(3);
    > vector v2(3);
    > v1 = x;
    > v2 = y;
    > int R = v1 * v2;
    > cout<< "R = "<< R;
    > return 0;
    > }
    >
    > Sincerely,
    > Srinivas Nayak


    What happens when you write v1 = x; is that vector(int *a) is called to
    create a temporary vector which then is assigned to v1 by calling the
    operator= which is generated for you by the compiler. In vector(int *a)
    v is uninitialized and you are writing to some random memory location
    (undefined behavior). Later the compiler generated operator= copies over
    the v and size from the temporary, overwriting the values that were in
    v1. At this point you loose the dynamically allocated v1.v pointer
    (memory leak).

    For the code you wrote to properly function you need to write a custom
    assignment operator and destructor and even though you're not using the
    copy constructor in the testcase you posted, in keeping with the so
    called "rule of three", you should also write a custom copy constructor.

    When you dynamically allocate memory you should always think about
    whether the pointers you are using actually point to memory you already
    initialized and you should always delete[] the memory at the latest when
    you are about to loose the last pointer to it.

    Have a nice day,
    Stefan
     
    Stefan van Kessel, Aug 18, 2010
    #2
    1. Advertising

  3. Srinu

    gwowen Guest

    On Aug 18, 12:49 pm, Srinu <> wrote:

    The problem is on these two lines:

    >         v1 = x;


    When you do this assignment, the compiler constructs a new temporary
    vector out of the arrays x[]. In effect, it does this

    vector xtmp(x); // (1)
    v1 = xtmp; // (2)

    Line (1) calls vector::vector(int*) which never sets xtmp.size or
    xtmp.v or allocates any memory. Then it copies an indeterminate
    amount from x[] (xtmp.size isn't initialized) to an indeterminate
    location (xtmp.v isn't initialised).
    Line (2) then calls the implicit operator=, which doesn't work as you
    expect either.
     
    gwowen, Aug 18, 2010
    #3
  4. Srinu

    Srinu Guest


    > What happens when you write v1 = x; is that vector(int *a) is called to
    > create a temporary vector which then is assigned to v1 by calling the
    > operator= which is generated for you by the compiler.



    will creation of temporary vector will happen even if I provide a
    operator= ?
     
    Srinu, Aug 18, 2010
    #4
  5. Srinu <> wrote:
    > using namespace std;
    >
    > class vector


    Yeah, very good idea. Very good idea.
     
    Juha Nieminen, Aug 18, 2010
    #5
  6. Juha Nieminen <>, on 18/08/2010 14:32:21, wrote:

    > Srinu<> wrote:
    >> using namespace std;
    >>
    >> class vector

    >
    > Yeah, very good idea. Very good idea.


    I was about to point out just the same thing.

    If the OP misses to catch the irony, I'll tell it explicitly: the std
    namespace includes a template called std::vector. Importing the whole
    std namespace into the global one and then creating stuff using the same
    names of other stuff contained by the std namespace is _absolutely not_
    a good idea - this could raise misleading error messages, conflicting
    names, and so on, that wouldn't be fun debugging.

    --
    FSC - http://userscripts.org/scripts/show/59948
    http://fscode.altervista.org - http://sardinias.com
     
    Francesco S. Carta, Aug 18, 2010
    #6
  7. On 8/18/2010 3:54 PM, Srinu wrote:
    >
    >> What happens when you write v1 = x; is that vector(int *a) is called to
    >> create a temporary vector which then is assigned to v1 by calling the
    >> operator= which is generated for you by the compiler.

    >
    >
    > will creation of temporary vector will happen even if I provide a
    > operator= ?


    If you only write a vector& operator=(const vector& r) then the
    temporary will still be created and all that changes is that your own
    operator=(const vector& r) will be called instead of the compiler
    generated one. If you also write a vector& operator=(int *a), then
    instead of creating the temporary and assigning it, the operator= taking
    a int* will be called.

    When you write "v1 = x;" that's the same as writing "v1.operator=(x);".
    At this point the compiler starts looking for a vector::eek:perator= that
    takes an argument of the type of x. If there is one i.e. operator=(int
    *a), that operator is used. If there isn't such a operator= the compiler
    goes on looking for a way to convert x to a type for which a operator=
    exists. In your case vector::vector(int *a) does offer a conversion from
    int* to vector so it is used. If you want to know the exact rules
    governing implicit conversion sequences, look at 13.3.3.1 in the standard.

    In addition to revisiting your book's chapters on constructors,
    assignment operators and destructors, you might benefit from reading the
    following article: http://www.drdobbs.com/cpp/184401400 ("C++ Made
    Easier: The Rule of Three" by Andrew Koenig and Barbara E. Moo)

    Have a nice day,
    Stefan
     
    Stefan van Kessel, Aug 19, 2010
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Dave Rudolf
    Replies:
    12
    Views:
    8,306
    Martijn Lievaart
    Feb 6, 2004
  2. Jeremy Smith
    Replies:
    2
    Views:
    591
    Jeremy Smith
    Aug 3, 2006
  3. Jess
    Replies:
    5
    Views:
    610
    Ron Natalie
    Jun 7, 2007
  4. Peng Yu
    Replies:
    5
    Views:
    401
    Juha Nieminen
    Sep 19, 2008
  5. srp113
    Replies:
    3
    Views:
    472
Loading...

Share This Page