1

Hi All I have written two codes

1.

    #include<iostream>
    using namespace std;
    void swap(int *x, int *y)
    {
        int t;
        t = *x;
        *x = *y;
        *y = t;
    }
    int main()
    {
        int a = 10, b = 20;
        cout << "value of a before swap " << a << endl;
        cout << "value of b before swap " << b << endl;
        swap(&a, &b);
        cout << "value of a after swap " << a << endl;
        cout << "value of b after swap " << b << endl;
        cin.get();

    }

2.

    #include<iostream>
    using namespace std;
    void swap(int *x, int *y)
    {
        int t;
        t = *x;
        *x = *y;
        *y = t;
    }
    int main()
    {
        int a = 10, b = 20;
        cout << "value of a before swap " << a << endl;
        cout << "value of b before swap " << b << endl;
        swap(a, b);
        cout << "value of a after swap " << a << endl;
        cout << "value of b after swap " << b << endl;
        cin.get();

    }

In both cases I am getting same output as value of a before swap 10 value of b before swap 20 value of a after swap 20 value of b after swap 10

My First question is Does swap(&a,&b) and swap(a,b) makes no difference to swap function??

But when i give same arguments to given below swap function

void swap(int &x, int &y)
{
    int t;
    t = x;
    x = y;
    y = t;
}

swap(a,b) gives no issue and work fine but when i pass value as swap(&a,&b) code gives Error error C2665: 'swap': none of the 3 overloads could convert all the argument types Why??

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • The `&` operator has two meanings in C++. It means `reference` in one context, and `address-of` in another. It seems you are not aware of this difference. – PaulMcKenzie Feb 01 '20 at 00:01
  • 1
    Please read (this is why case (2) compiles): https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice – Richard Critten Feb 01 '20 at 00:05
  • 5
    Also, your usage of `using namespace std;` is making your code **not** call your `swap` function. Instead, it is calling `std::swap`. This is another case where usage of `using namespace std;` just fouls things up. [See this to show that your code does not compile correctly when using your swap function](http://coliru.stacked-crooked.com/a/016b0790a3a33944). – PaulMcKenzie Feb 01 '20 at 00:07
  • 2
    You will do yourself a big favor by completely forgetting that "`using namespace std;`" is a part of C++. Otherwise you will keep confusing yourself with these kinds of confusing results. – Sam Varshavchik Feb 01 '20 at 00:12

3 Answers3

6

The problem is this evil line:

using namespace std;

In your second example, you're actually calling ::std::swap. Since your version of swap takes pointers, you must use the & operator.

See Why is “using namespace std;” considered bad practice?

Aykhan Hagverdili
  • 28,141
  • 6
  • 41
  • 93
1

In the first program there is called your own swap function for pointers.

In the second program there is called the standard function std::swap for objects of the type int due to unqualified name-lookup and presence of the using directive.

In the third program (when you supplied a and b) there is called your own function swap that accepts objects of the type int by reference. The compiler prefers to use a non-template function if both template and non-template functions are suitable.

But your swap function in the fourth program is not designed to swap pointers. So the compiler tries to select a standard swap function std::swap. But it is not designed to swap temporary (rvalues) objects. So the compiler issues an error.

You could call the standard swap function if you introduced intermediate variables that will contain pointers to variables a and b.

Here is a demonstrative program.

#include<iostream>
using namespace std;

void swap(int &x, int &y)
{
    int t;
    t = x;
    x = y;
    y = t;
}

int main()
{
    int a = 10, b = 20;
    int *pa = &a;
    int *pb = &b;

    cout << "value of *pa before swap " << *pa << endl;
    cout << "value of *pb before swap " << *pb << endl;

    swap( pa, pb); 

    cout << "value of *pa after swap " << *pa << endl;
    cout << "value of (pb after swap " << *pb << endl;

    cin.get();

}

Its output is

value of *pa before swap 10
value of *pb before swap 20
value of *pa after swap 20
value of (pb after swap 10  

In this program your own function swap is not called because its parameters are references to objects of the type int but you are calling swap passing objects (pointers) of the type int *.

So the standard function std::swap specialized for objects of the type int * is called.

It swaps the pointers themselves not the objects pointed to by the pointers..

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
-1

There is definitly a difference between 1 and 2

  1. You are taking the address of actually reserved memory devoted to ( holding ) your variables a and that is OK, you can effectively swap their content.

  2. You are considering the value of a and b to be a valid address but what I can assure you is that no OS gives you acces of those paricular zones in normal use so the address is wrong and the programs ends with a SEGFAULT and that is NOK.

Gold
  • 136
  • 6
  • 2
    This is wrong. If `using namespace std;` was omitted, there would be a compiler error for the second example. – 1201ProgramAlarm Feb 01 '20 at 00:22
  • 1
    The second part is incorrect. `a` and `b` are not implicitly convertible to `int*`, so OP's `swap` implementation is guaranteed to *not* be called by `swap(a, b)`. See the other answer for which `swap` is called. That `swap` has well defined behavior equivalent to OP's implementation and will not cause a segfault. – walnut Feb 01 '20 at 00:23
  • Thats correct using someone's else function is gona be OK but I'm trying to teach him what he is doing wrongm so he can be the next one I use a function.. Do you know what you qre tqlking about ? Using std does not solve everything magically if you don't include ... – Gold Feb 01 '20 at 00:39
  • @Gold Even if no standard library was involved, the program would not result in a segfault, because it will already fail to compile. The behavior you are describing cannot happen. The program would be ill-formed (diagnostic required). I do agree though that given that the proper includes for `std::swap` are missing, it is unspecified whether the program will compile with OP's observed behavior or whether it is going to fail as ill-formed with diagnostic required. – walnut Feb 01 '20 at 00:44
  • -fpermissive, or you cant declare an int to be an mmio register like everyone on arduino and embedded programming. I do, but I have an hand on it. Or even when programming an emulator ( tested ) of course it shoul not compile blindly. Anyway having the value 10 in a pointer is not impossible. – Gold Feb 01 '20 at 01:00
  • @Gold But that is GCC specific and then you are not really writing standard C++ anymore. The question did not specify that it is about such a C++ dialect. I am also not convinced that `-fpermissive` is a good idea even then. The proper way of obtaining a pointer to an address of a given integer value is not to rely on non-standard implicit casting, but to use `reinterpret_cast(a)`. (I don't really have any embedded experience though.) – walnut Feb 01 '20 at 01:07
  • Use the cast. It makes it immediately obvious to readers of the code that you're playing fast and loose with the typing and that since you're doing it explicitly you probably have a good reason. Turn off the type checking globally and you almost always regret it by not getting the warning/compiler error when you didn't mean for the conversion to take place. – user4581301 Feb 01 '20 at 01:23
  • Back in the good ol' days of embedded programming you wouldn't necessary get a segfault or crash over something like what's described. You would get a nightmare of debugging corrupted memory. Now that I think about it, those good ol' days weren't that good. – user4581301 Feb 01 '20 at 01:28
  • Arf the good is in the use of those little beasts, wicked quads. – Gold Feb 01 '20 at 03:01
  • Still if rishi seems to be a new comer in programming, I don't want to induce limitations in his passion. He may have defined a and b to be pointers the root errors is that he don't have ownership on 10 besides taking an int value for a valid pointer. – Gold Feb 01 '20 at 03:06
  • Understand and appreciate the goal, but disagree with the method. I found C and C++ a lot more enjoyable once I realize that I could do things I shouldn't. A lot of these guidelines are there to keep programmers from flaming out trying to debug stuff that should have been compiler error, not a bug. – user4581301 Feb 02 '20 at 06:23
  • Humm there are more embedded devices programmed that way per years than Personnal Computers in the world.. Often your life depends on them. – Gold Feb 03 '20 at 22:42