Operator () overloading, cannot return by value.

Discussion in 'C++' started by fabian.lim@gmail.com, Sep 8, 2008.

  1. Guest

    Hi All,

    Im a newbie to C++, I am trying to customize the vector template
    STL to a template Class. My code is shown below. Im confused about
    something and maybe somebody here might be able to help me.

    Lets say X is my vector, which contains 10 elements. I want to
    assign elements indexed 2 to 5 to another vector Y, so I want to do it
    like Y = X(2,5). So what I do is i overload the () operators, as
    marked in (a) below. This creates a new intermidate Vector class Z,
    via the constructor that is marked (b) below. The intermediate vector
    class is returned to (a), which thens try to return by value. However
    my memory always gets destroyed. This makes sense because I created a
    variable which has scope only in (a).

    However, when I add to vectors X + Y, again an intermediate result
    is created. This is done in (c) below. The X (lhs) argument is used to
    call another constructor which then creates a copy Z, and adds Y (rhs)
    to that copy Z. Now Z is then returned but it does not get destroyed.

    So to sum up, why does memory gets destroyed in the first case but
    not in the second. And how to avoid this problem in the first case?

    Thanks in advance.

    /*------------------------------------------------
    This is package for Vectors, Matrices (Template Class)
    --------------------------------------------------*/
    #include <iostream>
    #include <vector>
    #include <math.h>
    #define to ,
    using namespace std;

    //********************** START: VECTOR *************************
    template <typename TYPE>
    class Vector {
    vector<TYPE> v;
    public:
    //********************************************************
    // Selectors
    const TYPE& operator[](const int& k) const { return v[k]; } //default
    [] indexing
    const TYPE& operator()(const int& k) const {return v[k];}
    int size() const {return v.size();} //returns the size

    const Vector<TYPE> operator()(const int& i,const int& j) <---- (a)
    return Vector<TYPE>(v, i, j);

    //********************************************************
    // Constructors and Destructor
    Vector() { };
    ~Vector(){ };

    //********************************************************
    //plus operation
    Vector<TYPE>& operator+=(const Vector<TYPE>& rhs){
    for (int k = 0; k < rhs.size(); k++){
    if (k < v.size())
    v[k] += rhs[k];
    else v.push_back(rhs[k]);
    }
    return *this;
    }

    //********************************************************
    // Copiers
    //copy constructors
    Vector( const Vector<TYPE>& val) { //copy constructor for
    intermediate results (like x + y)
    for (int k = 0; k < val.size(); k++)
    v.push_back(val[k]);
    }
    Vector( const Vector<TYPE>& val, const int& i, const int& j)
    { <----- (b)
    //this constructor is used to create copy when indexing a range
    for (int k = i; k <=j; k++){
    if (k<val.size())
    v.push_back(val[k]);
    else v.push_back(0);
    }
    }

    //assignments
    Vector<TYPE>& operator=(const Vector<TYPE>& rhs) {
    v.clear();
    for (int k = 0; k < rhs.size(); k++)
    v.push_back(rhs[k]);
    return *this;
    }
    };

    //********************************************************
    //plus operation
    template <typename TYPE>
    inline const Vector<TYPE> operator+(const Vector<TYPE>& lhs, const
    Vector<TYPE>& rhs)
    {
    return Vector<TYPE>(lhs) += rhs; <----- (c)
    }


    //********************** END: VECTOR *************************
     
    , Sep 8, 2008
    #1
    1. Advertising

  2. maverik Guest

    Hi fabian.
    May be difference in this:

    const Vector<TYPE> operator()(const int& i,const int& j) <---- (a)
    {...}
    Vector<TYPE>& operator+=(const Vector<TYPE>& rhs){...}

    Should you use:

    const Vector<TYPE>& operator()(const int& i,const int& j) <---- (a)
    {...}

    instead

    const Vector<TYPE> operator()(const int& i,const int& j) <---- (a)
    {...}
     
    maverik, Sep 8, 2008
    #2
    1. Advertising

  3. maverik Guest

    Hi fabian.
    May be difference in this:

    const Vector<TYPE> operator()(const int& i,const int& j) <---- (a)
    {...}
    Vector<TYPE>& operator+=(const Vector<TYPE>& rhs){...}

    Should you use:

    const Vector<TYPE>& operator()(const int& i,const int& j) <---- (a)
    {...}

    instead

    const Vector<TYPE> operator()(const int& i,const int& j) <---- (a)
    {...}
     
    maverik, Sep 8, 2008
    #3
  4. Guest

    On 8 Sep, 08:53, wrote:
    > Hi All,
    >
    >    Im a newbie to C++, I am trying to customize the vector template
    > STL to a template Class. My code is shown below. Im confused about
    > something and maybe somebody here might be able to help me.
    >
    >    Lets say X is my vector, which contains 10 elements. I want to
    > assign elements indexed 2 to 5 to another vector Y, so I want to do it
    > like Y = X(2,5). So what I do is i overload the () operators, as
    > marked in (a) below. This creates a new intermidate Vector class Z,
    > via the constructor that is marked (b) below. The intermediate vector
    > class is returned to (a), which thens try to return by value. However
    > my memory always gets destroyed. This makes sense because I created a
    > variable which has scope only in (a).
    >
    >    However, when I add to vectors X + Y, again an intermediate result
    > is created. This is done in (c) below. The X (lhs) argument is used to
    > call another constructor which then creates a copy Z, and adds Y (rhs)
    > to that copy Z. Now Z is then returned but it does not get destroyed.
    >
    >    So to sum up, why does memory gets destroyed in the first case but
    > not in the second. And how to avoid this problem in the first case?
    >
    > Thanks in advance.
    >
    > /*------------------------------------------------
    > This is package for Vectors, Matrices (Template Class)
    > --------------------------------------------------*/
    > #include <iostream>
    > #include <vector>
    > #include <math.h>
    > #define to ,
    > using namespace std;
    >
    > //********************** START: VECTOR *************************
    > template <typename TYPE>
    > class Vector {
    >         vector<TYPE> v;
    > public:
    >         //********************************************************
    >         //    Selectors
    >         const TYPE& operator[](const int& k) const { return v[k]; } //default
    > [] indexing
    >         const TYPE& operator()(const int& k) const {return v[k];}
    >         int size() const {return v.size();} //returns the size
    >
    >         const Vector<TYPE> operator()(const int& i,const int& j) <---- (a)
    >                 return Vector<TYPE>(v, i, j);
    >
    >         //********************************************************
    >         //    Constructors and Destructor
    >         Vector() { };
    >         ~Vector(){ };
    >
    >         //********************************************************
    >         //plus operation
    >         Vector<TYPE>& operator+=(const Vector<TYPE>& rhs){
    >                 for (int k = 0; k < rhs.size(); k++){
    >                         if (k < v.size())
    >                                 v[k] += rhs[k];
    >                         else v.push_back(rhs[k]);
    >                 }
    >                 return *this;
    >         }
    >
    >         //********************************************************
    >         //    Copiers
    >         //copy constructors
    >         Vector( const Vector<TYPE>& val) { //copy constructor for
    > intermediate results (like x + y)
    >                 for (int k = 0; k < val.size(); k++)
    >                         v.push_back(val[k]);
    >         }
    >         Vector( const Vector<TYPE>& val, const int& i, const int& j)
    > {    <----- (b)
    >                 //this constructor is used to create copy when indexing a range
    >                 for (int k = i; k <=j; k++){
    >                         if (k<val.size())
    >                                 v.push_back(val[k]);
    >                         else v.push_back(0);
    >                 }
    >         }
    >
    >         //assignments
    >         Vector<TYPE>& operator=(const Vector<TYPE>& rhs) {
    >                 v.clear();
    >                 for (int k = 0; k < rhs.size(); k++)
    >                         v.push_back(rhs[k]);
    >                 return *this;
    >         }
    >
    > };
    >
    > //********************************************************
    > //plus operation
    > template <typename TYPE>
    > inline const Vector<TYPE> operator+(const Vector<TYPE>& lhs, const
    > Vector<TYPE>& rhs)
    > {
    >         return Vector<TYPE>(lhs) += rhs;   <----- (c)
    >
    > }
    >
    > //********************** END: VECTOR *************************


    Hi,

    I took the code, added a method to populate the vector and then it
    failed to compile. I changed the following:

    const Vector<TYPE> operator()(const int& i,const int& j) <---- (a)
    return Vector<TYPE>(v, i, j);

    to this:

    const Vector<TYPE> operator()(const int& i,const int& j) // <---- (a)
    {
    return Vector<TYPE>(*this, i, j); // <--- Changed to pass in
    *this, NOT v
    }

    and it worked. Your code was passing in the member variable v but
    there's no constructor on Vector for std::vector! I don't know how you
    got it to compile??

    The following program seemed to work okay and outputs "3,4,5" to the
    standard output:

    /*------------------------------------------------
    This is package for Vectors, Matrices (Template Class)
    --------------------------------------------------*/
    #include <iostream>
    #include <vector>
    #include <math.h>
    #define to ,
    using namespace std;


    //********************** START: VECTOR *************************
    template <typename TYPE>
    class Vector {
    vector<TYPE> v;
    public:
    //********************************************************
    // Selectors
    const TYPE& operator[](const int& k) const { return v[k]; } //
    default [] indexing
    const TYPE& operator()(const int& k) const {return v[k];}
    int size() const {return v.size();} //returns the size


    const Vector<TYPE> operator()(const int& i,const int& j)
    {
    return Vector<TYPE>(*this, i, j);
    }


    //********************************************************
    // Constructors and Destructor
    Vector() { };
    ~Vector(){ };


    //********************************************************
    //plus operation
    Vector<TYPE>& operator+=(const Vector<TYPE>& rhs){
    for (int k = 0; k < rhs.size(); k++){
    if (k < v.size())
    v[k] += rhs[k];
    else v.push_back(rhs[k]);
    }
    return *this;
    }


    //********************************************************
    // Copiers
    //copy constructors
    Vector( const Vector<TYPE>& val) { //copy constructor for
    intermediate results (like x + y)
    for (int k = 0; k < val.size(); k++)
    v.push_back(val[k]);
    }
    Vector( const Vector<TYPE>& val, const int& i, const int& j)
    {
    //this constructor is used to create copy when
    indexing a range
    for (int k = i; k <=j; k++){
    if (k<val.size())
    v.push_back(val[k]);
    else v.push_back(0);
    }
    }


    //assignments
    Vector<TYPE>& operator=(const Vector<TYPE>& rhs) {
    v.clear();
    for (int k = 0; k < rhs.size(); k++)
    v.push_back(rhs[k]);
    return *this;
    }

    void add(const TYPE& t)
    {
    v.push_back(t);
    }
    };


    //********************************************************
    //plus operation
    template <typename TYPE>
    inline const Vector<TYPE> operator+(const Vector<TYPE>& lhs, const
    Vector<TYPE>& rhs)
    {
    return Vector<TYPE>(lhs) += rhs;
    }

    int main()
    {
    Vector<int> vi;
    vi.add(1);
    vi.add(2);
    vi.add(3);
    vi.add(4);
    vi.add(5);
    vi.add(6);

    Vector<int> copyVec = vi(2,4);

    std::cout << copyVec[0] << ',' << copyVec[1] << ',' << copyVec[2] <<
    std::endl;

    }
     
    , Sep 8, 2008
    #4
  5. Guest

    On 8 Sep, 08:53, wrote:
    > Hi All,
    >
    >    Im a newbie to C++, I am trying to customize the vector template
    > STL to a template Class. My code is shown below. Im confused about
    > something and maybe somebody here might be able to help me.
    >
    >    Lets say X is my vector, which contains 10 elements. I want to
    > assign elements indexed 2 to 5 to another vector Y, so I want to do it
    > like Y = X(2,5). So what I do is i overload the () operators, as
    > marked in (a) below. This creates a new intermidate Vector class Z,
    > via the constructor that is marked (b) below. The intermediate vector
    > class is returned to (a), which thens try to return by value. However
    > my memory always gets destroyed. This makes sense because I created a
    > variable which has scope only in (a).
    >
    >    However, when I add to vectors X + Y, again an intermediate result
    > is created. This is done in (c) below. The X (lhs) argument is used to
    > call another constructor which then creates a copy Z, and adds Y (rhs)
    > to that copy Z. Now Z is then returned but it does not get destroyed.
    >
    >    So to sum up, why does memory gets destroyed in the first case but
    > not in the second. And how to avoid this problem in the first case?
    >
    > Thanks in advance.
    >
    > /*------------------------------------------------
    > This is package for Vectors, Matrices (Template Class)
    > --------------------------------------------------*/
    > #include <iostream>
    > #include <vector>
    > #include <math.h>
    > #define to ,
    > using namespace std;
    >
    > //********************** START: VECTOR *************************
    > template <typename TYPE>
    > class Vector {
    >         vector<TYPE> v;
    > public:
    >         //********************************************************
    >         //    Selectors
    >         const TYPE& operator[](const int& k) const { return v[k]; } //default
    > [] indexing
    >         const TYPE& operator()(const int& k) const {return v[k];}
    >         int size() const {return v.size();} //returns the size
    >
    >         const Vector<TYPE> operator()(const int& i,const int& j) <---- (a)
    >                 return Vector<TYPE>(v, i, j);
    >
    >         //********************************************************
    >         //    Constructors and Destructor
    >         Vector() { };
    >         ~Vector(){ };
    >
    >         //********************************************************
    >         //plus operation
    >         Vector<TYPE>& operator+=(const Vector<TYPE>& rhs){
    >                 for (int k = 0; k < rhs.size(); k++){
    >                         if (k < v.size())
    >                                 v[k] += rhs[k];
    >                         else v.push_back(rhs[k]);
    >                 }
    >                 return *this;
    >         }
    >
    >         //********************************************************
    >         //    Copiers
    >         //copy constructors
    >         Vector( const Vector<TYPE>& val) { //copy constructor for
    > intermediate results (like x + y)
    >                 for (int k = 0; k < val.size(); k++)
    >                         v.push_back(val[k]);
    >         }
    >         Vector( const Vector<TYPE>& val, const int& i, const int& j)
    > {    <----- (b)
    >                 //this constructor is used to create copy when indexing a range
    >                 for (int k = i; k <=j; k++){
    >                         if (k<val.size())
    >                                 v.push_back(val[k]);
    >                         else v.push_back(0);
    >                 }
    >         }
    >
    >         //assignments
    >         Vector<TYPE>& operator=(const Vector<TYPE>& rhs) {
    >                 v.clear();
    >                 for (int k = 0; k < rhs.size(); k++)
    >                         v.push_back(rhs[k]);
    >                 return *this;
    >         }
    >
    > };
    >
    > //********************************************************
    > //plus operation
    > template <typename TYPE>
    > inline const Vector<TYPE> operator+(const Vector<TYPE>& lhs, const
    > Vector<TYPE>& rhs)
    > {
    >         return Vector<TYPE>(lhs) += rhs;   <----- (c)
    >
    > }
    >
    > //********************** END: VECTOR *************************


    Hi,

    I took the code, added a method to populate the vector and then it
    failed to compile. I changed the following:

    const Vector<TYPE> operator()(const int& i,const int& j) <---- (a)
    return Vector<TYPE>(v, i, j);

    to this:

    const Vector<TYPE> operator()(const int& i,const int& j) // <---- (a)
    {
    return Vector<TYPE>(*this, i, j); // <--- Changed to pass in
    *this, NOT v
    }

    and it worked. Your code was passing in the member variable v but
    there's no constructor on Vector for std::vector! I don't know how you
    got it to compile??

    The following program seemed to work okay and outputs "3,4,5" to the
    standard output:

    /*------------------------------------------------
    This is package for Vectors, Matrices (Template Class)
    --------------------------------------------------*/
    #include <iostream>
    #include <vector>
    #include <math.h>
    #define to ,
    using namespace std;


    //********************** START: VECTOR *************************
    template <typename TYPE>
    class Vector {
    vector<TYPE> v;
    public:
    //********************************************************
    // Selectors
    const TYPE& operator[](const int& k) const { return v[k]; } //
    default [] indexing
    const TYPE& operator()(const int& k) const {return v[k];}
    int size() const {return v.size();} //returns the size


    const Vector<TYPE> operator()(const int& i,const int& j)
    {
    return Vector<TYPE>(*this, i, j);
    }


    //********************************************************
    // Constructors and Destructor
    Vector() { };
    ~Vector(){ };


    //********************************************************
    //plus operation
    Vector<TYPE>& operator+=(const Vector<TYPE>& rhs){
    for (int k = 0; k < rhs.size(); k++){
    if (k < v.size())
    v[k] += rhs[k];
    else v.push_back(rhs[k]);
    }
    return *this;
    }


    //********************************************************
    // Copiers
    //copy constructors
    Vector( const Vector<TYPE>& val) { //copy constructor for
    intermediate results (like x + y)
    for (int k = 0; k < val.size(); k++)
    v.push_back(val[k]);
    }
    Vector( const Vector<TYPE>& val, const int& i, const int& j)
    {
    //this constructor is used to create copy when
    indexing a range
    for (int k = i; k <=j; k++){
    if (k<val.size())
    v.push_back(val[k]);
    else v.push_back(0);
    }
    }


    //assignments
    Vector<TYPE>& operator=(const Vector<TYPE>& rhs) {
    v.clear();
    for (int k = 0; k < rhs.size(); k++)
    v.push_back(rhs[k]);
    return *this;
    }

    void add(const TYPE& t)
    {
    v.push_back(t);
    }
    };


    //********************************************************
    //plus operation
    template <typename TYPE>
    inline const Vector<TYPE> operator+(const Vector<TYPE>& lhs, const
    Vector<TYPE>& rhs)
    {
    return Vector<TYPE>(lhs) += rhs;
    }

    int main()
    {
    Vector<int> vi;
    vi.add(1);
    vi.add(2);
    vi.add(3);
    vi.add(4);
    vi.add(5);
    vi.add(6);

    Vector<int> copyVec = vi(2,4);

    std::cout << copyVec[0] << ',' << copyVec[1] << ',' << copyVec[2] <<
    std::endl;

    }
     
    , Sep 8, 2008
    #5
  6. Guest

    On 8 Sep, 10:02, maverik <> wrote:
    > Hi fabian.
    > May be difference in this:
    >
    > const Vector<TYPE>  operator()(const int& i,const int& j) <---- (a)
    > {...}
    >       Vector<TYPE>& operator+=(const Vector<TYPE>& rhs){...}
    >
    > Should you use:
    >
    > const Vector<TYPE>&  operator()(const int& i,const int& j) <---- (a)
    > {...}
    >
    > instead
    >
    > const Vector<TYPE>  operator()(const int& i,const int& j) <---- (a)
    > {...}


    No. If he changed operator() to return a reference, it would return a
    reference to the temporary which would be out of scope once operator()
    has completed. The reference would be referring to a dead object.
     
    , Sep 8, 2008
    #6
  7. Guest

    On 8 Sep, 10:02, maverik <> wrote:
    > Hi fabian.
    > May be difference in this:
    >
    > const Vector<TYPE>  operator()(const int& i,const int& j) <---- (a)
    > {...}
    >       Vector<TYPE>& operator+=(const Vector<TYPE>& rhs){...}
    >
    > Should you use:
    >
    > const Vector<TYPE>&  operator()(const int& i,const int& j) <---- (a)
    > {...}
    >
    > instead
    >
    > const Vector<TYPE>  operator()(const int& i,const int& j) <---- (a)
    > {...}


    No. If he changed operator() to return a reference, it would return a
    reference to the temporary which would be out of scope once operator()
    has completed. The reference would be referring to a dead object.
     
    , Sep 8, 2008
    #7
  8. Guest

    Hi newbar and Maverik,

    Thanks you both for your prompt reply. Newbar, I cant believe it
    actually works. Yes you are right about lacking a constructor for
    std:vector<TYPE>, actually I modified my code when i was posting and
    made a mistake there.

    The funny thing is I actually tried out the same thing you suggested
    (before I posted), and I thought I saw that it didnt work, however
    when I tried again after I read your post, it seemed to work. The only
    thing is that I was programming on Windows before, and now I tried It
    on a Mac.

    I will go back to school tomorrow to try it out again on Windows.


    On Sep 7, 11:22 pm, wrote:
    > On 8 Sep, 10:02, maverik <> wrote:
    >
    >
    >
    > > Hi fabian.
    > > May be difference in this:

    >
    > > const Vector<TYPE> operator()(const int& i,const int& j) <---- (a)
    > > {...}
    > > Vector<TYPE>& operator+=(const Vector<TYPE>& rhs){...}

    >
    > > Should you use:

    >
    > > const Vector<TYPE>& operator()(const int& i,const int& j) <---- (a)
    > > {...}

    >
    > > instead

    >
    > > const Vector<TYPE> operator()(const int& i,const int& j) <---- (a)
    > > {...}

    >
    > No. If he changed operator() to return a reference, it would return a
    > reference to the temporary which would be out of scope once operator()
    > has completed. The reference would be referring to a dead object.
     
    , Sep 8, 2008
    #8
  9. Guest

    Hi newbar and Maverik,

    Thanks you both for your prompt reply. Newbar, I cant believe it
    actually works. Yes you are right about lacking a constructor for
    std:vector<TYPE>, actually I modified my code when i was posting and
    made a mistake there.

    The funny thing is I actually tried out the same thing you suggested
    (before I posted), and I thought I saw that it didnt work, however
    when I tried again after I read your post, it seemed to work. The only
    thing is that I was programming on Windows before, and now I tried It
    on a Mac.

    I will go back to school tomorrow to try it out again on Windows.


    On Sep 7, 11:22 pm, wrote:
    > On 8 Sep, 10:02, maverik <> wrote:
    >
    >
    >
    > > Hi fabian.
    > > May be difference in this:

    >
    > > const Vector<TYPE> operator()(const int& i,const int& j) <---- (a)
    > > {...}
    > > Vector<TYPE>& operator+=(const Vector<TYPE>& rhs){...}

    >
    > > Should you use:

    >
    > > const Vector<TYPE>& operator()(const int& i,const int& j) <---- (a)
    > > {...}

    >
    > > instead

    >
    > > const Vector<TYPE> operator()(const int& i,const int& j) <---- (a)
    > > {...}

    >
    > No. If he changed operator() to return a reference, it would return a
    > reference to the temporary which would be out of scope once operator()
    > has completed. The reference would be referring to a dead object.
     
    , Sep 8, 2008
    #9
    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. John Smith
    Replies:
    2
    Views:
    453
    Ivan Vecerina
    Oct 6, 2004
  2. Greenhorn
    Replies:
    15
    Views:
    887
    Keith Thompson
    Mar 6, 2005
  3. Replies:
    11
    Views:
    771
    James Kanze
    May 16, 2007
  4. hurcan solter
    Replies:
    3
    Views:
    760
    Cholo Lennon
    Aug 29, 2007
  5. Replies:
    11
    Views:
    587
Loading...

Share This Page