Q:

Swapping two integer numbers with no temporary variable

I tried to swap 2 integer numbers without using an additional variable as a traditional swap.
Is it legal in C++? My VC compiler doesn't complain nor gives any warning about it. If so, how can I improve this script?
#include <iostream>

int main()
{
    int a = 20;
    int b = 66;

    // before swapping
    std::cout << a  << ' ' << b  << '\n';

    // swap
    a ^= b ^= a ^= b;

    // after swapping
    std::cout << a << ' ' << b << '\n';
}

For this code:
int a = 20;
int b = 66;
a ^= b ^= a ^= b;

Assembler output for VC++ 2013:

_b$ = -20                     ; size = 4
_a$ = -8                      ; size = 4

mov   DWORD PTR _a$[ebp], 20          ; 00000014H
mov   DWORD PTR _b$[ebp], 66          ; 00000042H

mov   eax, DWORD PTR _a$[ebp]
xor   eax, DWORD PTR _b$[ebp]
mov   DWORD PTR _a$[ebp], eax

mov   ecx, DWORD PTR _b$[ebp]
xor   ecx, DWORD PTR _a$[ebp]
mov   DWORD PTR _b$[ebp], ecx

mov   edx, DWORD PTR _a$[ebp]
xor   edx, DWORD PTR _b$[ebp]
mov   DWORD PTR _a$[ebp], edx

For this code:
int a = 20;
int b = 66;

int t = a;
a = b;
b = t;

Assembler output for VC++ 2013:

_t$ = -32                     ; size = 4
_b$ = -20                     ; size = 4
_a$ = -8                      ; size = 4

mov   DWORD PTR _a$[ebp], 20          ; 00000014H
mov   DWORD PTR _b$[ebp], 66          ; 00000042H

mov   eax, DWORD PTR _a$[ebp]
mov   DWORD PTR _t$[ebp], eax

mov   eax, DWORD PTR _b$[ebp]
mov   DWORD PTR _a$[ebp], eax

mov   eax, DWORD PTR _t$[ebp]
mov   DWORD PTR _b$[ebp], eax

A:

You make assumptions which may not be true. Why do you believe that
int tmp = a;
a = b;
b = tmp;                                  

actually is compiled down to using an actual variable? It is likely just a register used on the CPU.
Have you inspected it?
Further, why do you assume that:
a ^= b ^= a ^= b;

uses fewer registers than a swap?
Really, what you should do is:
#include <algorithm>
#include <iostream>

int main() {

    int a = 20;
    int b = 66;

    // before swapping
    std::cout << a  << ' ' << b  << '\n';

    // swap
    std::swap(a,b);

    // after swapping
    std::cout << a << ' ' << b << '\n';

}

Which is also a reminder that having the a ^= b ^= a ^= b; 'naked' in your code is not good practice. Something like that should be embedded in a function, not directly in the main method.
Update - assembler output
For the code:
int a = 20;
int b = 66;

int t = a;
a = b;
b = t;

return a;

you get the assembler output:
movl    $20, -12(%rbp)
movl    $66, -8(%rbp)
movl    -12(%rbp), %eax
movl    %eax, -4(%rbp)
movl    -8(%rbp), %eax
movl    %eax, -12(%rbp)
movl    -4(%rbp), %eax
movl    %eax, -8(%rbp)
movl    -12(%rbp), %eax
popq    %rbp

For the code:
int a = 20;
int b = 66;

a ^= b ^= a ^= b;

return a;

you get
movl    $20, -8(%rbp)
movl    $66, -4(%rbp)
movl    -4(%rbp), %eax
xorl    %eax, -8(%rbp)
movl    -8(%rbp), %eax
xorl    %eax, -4(%rbp)
movl    -4(%rbp), %eax
xorl    %eax, -8(%rbp)
movl    -8(%rbp), %eax
popq    %rbp

What does that show?

It shows that both systems run in 12 instructions, including the copy to the stack (%rbp)
that both systems use the single register %eax
both systems use the stack as a temp store for the result (the XOR reuses -8 and -4 offsets in the stack, the tmp uses -12(%rbp)

Net result? Both systems use less than 16 bytes of the stack, they both use 1 register in addition to the stack, and they both have the same number of instructions.
I know which one is more readable....
Of course, with the above code, if I add -O2 to the optimization, I get the assembler:
movl    $66, %eax
ret

which, as you can imagine, is fast.

A:

This is not valid C++, unless you consider code that allows a conforming compiler to wipe your hard drive, conjure nasal demons and make your cat pregnant to be valid C++.
This statement
a ^= b ^= a ^= b;

invokes undefined behavior. Pre-C++11, it modifies a twice without an intervening sequence point, which causes undefined behavior. Post-C++11, the rules are more complex, but the result is the same. I'm not really inclined to write a full analysis since the subject has been beaten to death multiple times on StackOverflow, but it is essentially identical to the analysis for i += ++i + 1; in this SO answer.
a ^= b;
b ^= a;
a ^= b;

This would be valid C++, and the well-known XOR swap trick. However, it generally is not a performance improvement, and decreases the readability of your code.

A:

Assuming that a+b is less than the maximum size of an integer on your system, why not try a simpler solution?
a = a + b 
b = a - b
a = a - b

For example
Initial
a = 2
b = 4

a = a + b
a = 2 + 4
a = 6

b = a - b
b = 6 - 4
b = 2

a = a - b
a = 6 - 2
a = 4

Final
a = 4
b = 2

