Part of the confusion about "Pass by reference" comes from the C language, where passing a pointer as a function argument, was given this terminology. Edit:
Apparently that is not strictly correct: everything in C is "pass by value". Passing a pointer argument gives the illusion of pass by reference. But this link says that "Pass by reference" is still technically correct:
http://clc-wiki.net/wiki/C_language:Terms:Pass_by_reference
To me, the name of the pointer variable is the alias for the variable.
But C++ has actual references which is a different concept.
It is tempting to think of references as const pointers (they can't be re-seated to point at something else ) , mainly because they behave like pointers, except that one can't have a container of references - there is
std::reference_wrapper
for that.
Clues about what actually happens with references can be gained by looking
std::add_lvalue_reference
. I gather this works like the other traits: it uses TMP (Template Meta Programming ). On my system at least, there is a struct which adds the references to the type. TMP is an altogether different concept, but by reading through the type_traits header file, one can see how the various traits are built up. Some code from my system below.
http://en.cppreference.com/w/cpp/types/add_reference
One would hope that when the compiler comes across a reference variable, it does something similar to the traits to make it a reference.
I still find it hard to think about how it would work without there being a pointer in there
somewhere :+) I mean it is one thing to have member that says that it is a reference, but it is another to pass or move an object without copying it - which is the main point of passing by reference, indeed of pointers from C.
Maybe because is wrapped up in a bunch of TMP, it is wrong to think of it as being purely a pointer?
type_traits header file
1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693
|
// Reference transformations.
/// remove_reference
template<typename _Tp>
struct remove_reference
{ typedef _Tp type; };
template<typename _Tp>
struct remove_reference<_Tp&>
{ typedef _Tp type; };
template<typename _Tp>
struct remove_reference<_Tp&&>
{ typedef _Tp type; };
template<typename _Tp, bool = __is_referenceable<_Tp>::value>
struct __add_lvalue_reference_helper
{ typedef _Tp type; };
template<typename _Tp>
struct __add_lvalue_reference_helper<_Tp, true>
{ typedef _Tp& type; };
/// add_lvalue_reference
template<typename _Tp>
struct add_lvalue_reference
: public __add_lvalue_reference_helper<_Tp>
{ };
template<typename _Tp, bool = __is_referenceable<_Tp>::value>
struct __add_rvalue_reference_helper
{ typedef _Tp type; };
template<typename _Tp>
struct __add_rvalue_reference_helper<_Tp, true>
{ typedef _Tp&& type; };
/// add_rvalue_reference
template<typename _Tp>
struct add_rvalue_reference
: public __add_rvalue_reference_helper<_Tp>
{ };
#if __cplusplus > 201103L
/// Alias template for remove_reference
template<typename _Tp>
using remove_reference_t = typename remove_reference<_Tp>::type;
/// Alias template for add_lvalue_reference
template<typename _Tp>
using add_lvalue_reference_t = typename add_lvalue_reference<_Tp>::type;
/// Alias template for add_rvalue_reference
template<typename _Tp>
using add_rvalue_reference_t = typename add_rvalue_reference<_Tp>::type;
#endif
|