C++ References and const References
A reference is another name (an alias) for an existing variable. It is written with & in the declaration.
#include <iostream>
int main() {
int a = 10;
int& ref = a; // ref is another name of a
ref = 20;
std::cout << a << ' ' << ref << ' ' << (&a == &ref) << '\n';
}
20 20 1
Pass by reference
With a reference parameter, the function works on the original variable, with no copy.
#include <iostream>
void swap_values(int& x, int& y) {
int temp = x;
x = y;
y = temp;
}
int main() {
int a = 1, b = 2;
swap_values(a, b);
std::cout << a << ' ' << b << '\n';
}
2 1
const reference: fast and safe
For big objects, pass by const T&. No copy is made, and the function can not change the object.
#include <iostream>
#include <string>
#include <vector>
void print_all(const std::vector<std::string>& names) { // no copy, read only
for (const auto& n : names) std::cout << n << ' ';
std::cout << '\n';
}
int main() {
std::vector<std::string> names = {"Riya", "Aman", "Meera"};
print_all(names);
}
Riya Aman Meera
#include <string>
void change(const std::string& s) {
s += "!"; // error: s is const
}
int main() { }
Readonly.cpp: In function 'void change(const std::string&)':
Readonly.cpp:4:7: error: no match for 'operator+=' (operand types are 'const std::string' {aka 'const std::__cxx11::basic_string<char>'} and 'const char [2]')
4 | s += "!"; // error: s is const
| ~~^~~~~~
• there are 5 candidates
In file included from /usr/local/include/c++/16.2.0/string:58,
from Readonly.cpp:1:
• candidate 1: 'constexpr std::__cxx11::basic_string<_CharT, _Traits, _Alloc>& std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::operator+=(const std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]' (near match)
/usr/local/include/c++/16.2.0/bits/basic_string.h:1501:7:
1501 | operator+=(const basic_string& __str)
| ^~~~~~~~
• passing 'const std::string*' {aka 'const std::__cxx11::basic_string<char>*'} as 'this' argument discards qualifiers
• candidate 2: 'constexpr std::__cxx11::basic_string<_CharT, _Traits, _Alloc>& std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::operator+=(const _CharT*) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]' (near match)
/usr/local/include/c++/16.2.0/bits/basic_string.h:1511:7:
1511 | operator+=(const _CharT* __s)
| ^~~~~~~~
• passing 'const std::string*' {aka 'const std::__cxx11::basic_string<char>*'} as 'this' argument discards qualifiers
• candidate 3: 'constexpr std::__cxx11::basic_string<_CharT, _Traits, _Alloc>& std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::operator+=(_CharT) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]' (near match)
/usr/local/include/c++/16.2.0/bits/basic_string.h:1521:7:
1521 | operator+=(_CharT __c)
| ^~~~~~~~
• conversion of argument 1 would be ill-formed:
• error: invalid conversion from 'const char*' to 'char' [-fpermissive]
Readonly.cpp:4:10:
4 | s += "!"; // error: s is const
| ^~~
| |
| const char*
• candidate 4: 'template<class _Tp> constexpr std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::_If_sv<_Tp, std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&> std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::operator+=(const _Tp&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]'
/usr/local/include/c++/16.2.0/bits/basic_string.h:1548:9:
1548 | operator+=(const _Tp& __svt)
| ^~~~~~~~
• template argument deduction/substitution failed:
In file included from /usr/local/include/c++/16.2.0/bits/char_traits.h:52,
from /usr/local/include/c++/16.2.0/string:45:
• /usr/local/include/c++/16.2.0/type_traits: In substitution of 'template<bool _Cond, class _Tp> using std::enable_if_t = typename std::enable_if::type [with bool _Cond = false; _Tp = std::__cxx11::basic_string<char>&]':
• required by substitution of 'template<class _CharT, class _Traits, class _Alloc> template<class _Tp, class _Res> using std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::_If_sv = std::enable_if_t<((bool)std::__and_<std::is_convertible<const _Tp&, std::basic_string_view<_CharT, _Traits> >, std::__not_<std::is_convertible<const _Tp*, const std::__cxx11::basic_string<_CharT, _Traits, _Alloc>*> >, std::__not_<std::is_convertible<const _Tp&, const _CharT*> > >::value), _Res> [with _Tp = char [2]; _Res = std::__cxx11::basic_string<char>&; _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]'
/usr/local/include/c++/16.2.0/bits/basic_string.h:159:8:
159 | using _If_sv = enable_if_t<
| ^~~~~~
• required by substitution of 'template<class _Tp> constexpr std::__cxx11::basic_string<char>::_If_sv<_Tp, std::__cxx11::basic_string<char>&> std::__cxx11::basic_string<char>::operator+=(const _Tp&) [with _Tp = char [2]]'
/usr/local/include/c++/16.2.0/bits/basic_string.h:1548:2:
1548 | operator+=(const _Tp& __svt)
| ^~~~~~~~
• required from here
Readonly.cpp:4:10:
4 | s += "!"; // error: s is const
| ^~~
• error: no type named 'type' in 'struct std::enable_if<false, std::__cxx11::basic_string<char>&>'
/usr/local/include/c++/16.2.0/type_traits:2946:11:
2946 | using enable_if_t = typename enable_if<_Cond, _Tp>::type;
| ^~~~~~~~~~~
• candidate 5: 'constexpr std::__cxx11::basic_string<_CharT, _Traits, _Alloc>& std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::operator+=(std::initializer_list<_Tp>) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]'
/usr/local/include/c++/16.2.0/bits/basic_string.h:1535:7:
1535 | operator+=(initializer_list<_CharT> __l)
| ^~~~~~~~
• no known conversion for argument 1 from 'const char [2]' to 'std::initializer_list<char>'
/usr/local/include/c++/16.2.0/bits/basic_string.h:1535:43:
1535 | operator+=(initializer_list<_CharT> __l)
| ~~~~~~~~~~~~~~~~~~~~~~~~~^~~
References vs pointers
| Point | Reference | Pointer |
|---|---|---|
| Must be initialized | Yes | No |
| Can be null | No | Yes (nullptr) |
| Can point to another variable later | No | Yes |
| Syntax to use | Like a normal variable | Needs * and -> |
Do not return a reference to a local variable
The local variable is destroyed when the function ends, so the reference would point to nothing. Modern GCC even refuses to compile this code:
int& bad() {
int local = 5;
return local; // local dies when the function ends
}
int main() {
bad();
}
Dangling.cpp: In function 'int& bad()':
Dangling.cpp:3:12: error: cannot bind non-const lvalue reference of type 'int&' to an rvalue of type 'int'
3 | return local; // local dies when the function ends
| ^~~~~
| Exercises & Assignments |
|---|
| No Content Found. |
| Interview Questions & Answers |
|---|
| No Content Found. |