Thread: Swap between two references.

  1. #1
    Registered User
    Join Date
    May 2013
    Posts
    228

    Swap between two references.

    Hi guys.

    I need some clarification.

    I have the following code segment:
    Code:
    void Swap(Number& num1, Number& num2)
    {
        cout<<"Before swap:"<<num1<<" "<<num2<<endl;
        Number& temp=num1;
        num1=num2;
        num2=temp;
        cout<<"After swap:"<<num1<<" "<<num2<<endl;
    }
    
    int main()
    {
        Int n1(13), n2(11);
        Swap(n1,n2);
        cout<<n1<<" "<<n2;
    }
    to which the output is:
    Code:
    Before swap:13 11
    After swap:13 11
    13 11
    that seems confusing.
    why doesn't Swap() swap the two Numbers?
    Last edited by Absurd; 05-28-2013 at 01:52 AM.

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    I suspect that you have bugs in your program in code that you did not show.

    To illustrate this, compile and run this program:
    Code:
    #include <iostream>
    
    using namespace std;
    
    void Swap(int& num1, int& num2)
    {
        cout<<"Before swap:"<<num1<<" "<<num2<<endl;
        int& temp=num1;
        num1=num2;
        num2=temp;
        cout<<"After swap:"<<num1<<" "<<num2<<endl;
    }
     
    int main()
    {
        int n1(13), n2(11);
        Swap(n1,n2);
        cout<<n1<<" "<<n2<<endl;
    }
    You should get this output:
    Code:
    Before swap:13 11
    After swap:11 11
    11 11
    The reason is that the reference can be viewed as an alias, so the Swap function above is equivalent to:
    Code:
    void Swap(int& num1, int& num2)
    {
        cout<<"Before swap:"<<num1<<" "<<num2<<endl;
        num1=num2;
        num2=num1;
        cout<<"After swap:"<<num1<<" "<<num2<<endl;
    }
    which obviously makes both num1 and num2 have the same value, i.e., the value of num2 when the function is called.

    Your code, on the other hand, does something different, so my explanation is that you have a bug elsewhere too.

    EDIT:
    Also, I am assuming that Number is an (abstract) base class, and besides Int, you might have other subclasses, e.g., Double. In that case, what does it mean to swap an Int and a Double? Maybe you are just better off defining a swap function for each subclass, if it can do better than std::swap.
    Last edited by laserlight; 05-28-2013 at 01:59 AM.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User
    Join Date
    May 2013
    Posts
    228
    Hi laserlight.

    yes, Number is abstract, but there are only two subclasses: Double and Int.
    a swap will only be made between two Doubles or two Ints, never between a Double and an Int, I mean, I intend to make it a private method such that only I can use it.

    these two derived classes are pretty simple, there's nothing too fancy there.
    here's the .h files.

    Code:
    class Number
    {
    public:
        virtual ~Number(){}
        virtual bool operator==(const Number &number)const=0;
        virtual bool operator<(const Number &number)const=0;
        virtual bool operator>(const Number &number)const=0;
        virtual ostream& print(ostream& os)const=0;
        friend ostream& operator<<(ostream& os, const Number& number);
    };
    
    
    class Int: public Number
    {
    private:
        int m_iValue;
        virtual ostream& print(ostream& os)const;
    public:
        Int(int iValue=0):m_iValue(iValue){}
        virtual ~Int(){}
        virtual bool operator==(const Number& number)const;
        virtual bool operator<(const Number& number)const;
        virtual bool operator>(const Number& number)const;
    };
    
    
    class Double: public Number
    {
    private:
        double m_dValue;
        virtual ostream& print(ostream& os)const;
    public:
        Double(double dValue=0):m_dValue(dValue){}
        virtual ~Double(){}
        virtual bool operator==(const Number& number)const;
        virtual bool operator<(const Number& number)const;
        virtual bool operator>(const Number& number)const;
    };
    the .cpp contains simple definitions of these methods.
    I can post it too if it's relevant.

    Thanks.
    Last edited by Absurd; 05-28-2013 at 02:15 AM.

  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Absurd
    a swap will only be made between two Doubles or two Ints, never between a Double and an Int, I mean, I intend to make it a private method such that only I can use it.
    Then you don't need to define your own swap functions: use std::swap. If you do define your own swap functions, there should be one for each subclass.

    Quote Originally Posted by Absurd
    these two derived classes are pretty simple, there's nothing too fancy there.
    Indeed, so I don't see how you could have gotten the output that you did.

    EDIT:
    Oh, I understand: you are trying to swap via the Number references. However, operator= for Number does an assignment that does not copy any member variable, so you ended up assigning the Number sub-object parts of the Int objects, i.e., there was no net change since the m_iValue members were not assigned.
    Last edited by laserlight; 05-28-2013 at 02:39 AM.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  5. #5
    Registered User antred's Avatar
    Join Date
    Apr 2012
    Location
    Germany
    Posts
    257
    Quote Originally Posted by Absurd View Post
    to which the output is:
    Code:
    Before swap:13 11
    After swap:13 11
    13 11
    that seems confusing.
    why doesn't Swap() swap the two Numbers?
    Because you're doing it wrong. Change this line

    Code:
    Number& temp=num1;
    to this

    Code:
    Number temp=num1;
    and it'll work.

    P.S. Explanation: By writing Number& temp=num1; you're not creating a third instance of Number, you're creating a reference to an existing instance of Number, namely to whichever instance your num1 reference was pointing.

    P.S. #2: Sorry, that'll teach me to reply to a thread without reading the other replies first.
    Last edited by antred; 05-28-2013 at 05:43 AM.

  6. #6
    Registered User
    Join Date
    May 2013
    Posts
    228
    Thank you both for the help.
    I found a workaround in which I don't have to swap between two Number's.
    It seems like it can't be done when Number is abstract anyway...

    Quote Originally Posted by laserlight View Post
    EDIT:
    Oh, I understand: you are trying to swap via the Number references. However, operator= for Number does an assignment that does not copy any member variable, so you ended up assigning the Number sub-object parts of the Int objects, i.e., there was no net change since the m_iValue members were not assigned.
    I thought that when I don't implement the assignment =operator the compiler makes it with shallow copying.
    or at least I would expect it to complain that it didn't find the right definition for it ("no match for ‘operator ’=..." etc)...

  7. #7
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Absurd
    I found a workaround in which I don't have to swap between two Number's.
    What workaround is that?

    Quote Originally Posted by Absurd
    It seems like it can't be done when Number is abstract anyway...
    It can be done, e.g., you could have determined the derived types involved (normally should be avoided, but it can be done) and then swapped based on that, but... again, what would it mean to swap an Int and a Double?

    Quote Originally Posted by Absurd
    I thought that when I don't implement the assignment =operator the compiler makes it with shallow copying.
    or at least I would expect it to complain that it didn't find the right definition for it ("no match for ‘operator ’=..." etc)...
    The compiler did indeed generate a copy assignment operator that does shallow copying. The thing is, the copy assignment operator that was used was the copy assignment operator for Number, not for Int, but you want to use the one for Int. The reason why the copy assignment operator for Number was used is that in the context of your original Swap function, the parameters and local variable were references to Number, and the copy assignment operator is not virtual.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  8. #8
    Registered User
    Join Date
    May 2013
    Posts
    228
    Quote Originally Posted by laserlight View Post
    What workaround is that?
    well... it's not really a workaround as much as it is a different way to complete the assignment.

    I needed it so I can sort a linked list of Numbers.
    I wanted to avoid manipulation with pointers and just swap between values of nodes instead.
    I think I'll just handle it differently.

  9. #9
    Registered User
    Join Date
    Apr 2013
    Posts
    1,658
    There's always the classic method of swapping that doesn't use a temp variable:

    a ^= b
    b ^= a
    a ^= b

    but this probably wouldn't be to useful for what you want.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. off by one and help with swap
    By jrb47 in forum C++ Programming
    Replies: 1
    Last Post: 11-11-2006, 07:45 PM
  2. swap()? (g++)
    By jafet in forum C++ Programming
    Replies: 4
    Last Post: 08-05-2006, 04:59 PM
  3. swap()
    By divineleft in forum C++ Programming
    Replies: 13
    Last Post: 07-16-2006, 02:40 PM
  4. Swap a bit
    By mr_nice! in forum C Programming
    Replies: 7
    Last Post: 03-01-2004, 03:15 AM
  5. declare references to references works!
    By ManuelH in forum C++ Programming
    Replies: 4
    Last Post: 01-20-2003, 08:14 AM