What is the difference between a pointer and a reference in C++?
A reference is another name for an existing object; a pointer is a variable holding an address. A pointer can be null, re-pointed and used in arithmetic; a reference is bound once, at initialization.
Take
const T&orT&when an object must exist, and a pointer when "no object" is valid. See references vs pointers.Practice it: Reverse Linked List, Linked List Cycle
Which can a function change: an argument by value, by reference or by pointer?
C++#include <iostream> using namespace std; void byValue(int x) { x = 10; } void byRef(int& x) { x = 20; } void byPtr(int* x) { *x = 30; } int main() { int a = 1, b = 1, c = 1; byValue(a); byRef(b); byPtr(&c); cout << a << " " << b << " " << c << "\n"; }It prints
1 20 30.byValuechanges a copy,byRefchangesbitself, andbyPtrwrites through the address ofc.Pass small types by value, large read-only objects by
const T&, objects you modify byT&, and a pointer when the argument may be absent.Can you make a reference refer to a different variable?
C++#include <iostream> using namespace std; int main() { int a = 1, b = 2; int& r = a; r = b; r = 3; cout << a << " " << b << "\n"; }It prints
3 2. A reference cannot be re-pointed:r = b;assigns the value ofb(2) toa, andr = 3;assigns 3 toa.bis never touched.If you need a rebindable reference, for example inside a container, use a pointer or
std::reference_wrapper.What do
*p,p[-1]andp - agive afterp += 2?C++#include <iostream> using namespace std; int main() { int a[] = {10, 20, 30, 40}; int* p = a; p += 2; cout << *p << " " << p[-1] << " " << (p - a) << "\n"; }It prints
30 20 2. Pointer arithmetic counts in elements, sop += 2moves toa[2],p[-1]isa[1], andp - ais the number of elements between them.Moving a pointer outside the array (past one-past-the-end) is undefined behavior even without a dereference.
What is the difference between
const int*,int* constandconst int* const?Read the declaration from right to left:
const int* p: pointer to a const int. You can movep, not change*p.int* const p: const pointer. You can change*p, notp.const int* const p: neither can change.
int x = 1, y = 2; const int* a = &x; a = &y; // ok // *a = 5; error: *a is const int* const b = &x; *b = 5; // ok // b = &y; error: b is constWhat is the difference between
nullptrandNULL?nullptr(C++11) converts to any pointer type but never to an integer.NULLis a C macro,0on MSVC and the integer constant__nullon GCC and Clang with glibc.C++#include <iostream> void f(int) { std::cout << "f(int)\n"; } void f(int*) { std::cout << "f(int*)\n"; } int main() { f(0); f(nullptr); }This prints
f(int)and thenf(int*).f(NULL)callsf(int)on MSVC, is ambiguous with glibc, and callsf(int*)with musl (this page's runner).What is a dangling pointer, and how do you avoid it?
A pointer or reference to an object that no longer exists; using it is undefined behavior.
int* p = new int(5); delete p; // p now dangles *p = 6; // undefined behavior int& bad() { int local = 42; return local; // reference to a destroyed local } std::vector<int> v = {1, 2, 3}; int* first = &v[0]; v.push_back(4); // may reallocate: first can dangleAvoid it with owning types (
std::unique_ptr, containers), by returning by value, and by not keeping pointers into a vector acrosspush_back. AddressSanitizer catches most cases.What is the
thispointer in C++?A pointer, inside every non-static member function, to the object the function was called on. It separates a member from a parameter (
this->x = x;) and lets a method return*thisso calls chain.C++#include <iostream> #include <string> using namespace std; class Query { string sql = "SELECT *"; public: Query& from(const string& t) { sql += " FROM " + t; return *this; } Query& where(const string& c) { sql += " WHERE " + c; return *this; } string str() const { return sql; } }; int main() { cout << Query().from("users").where("age > 18").str() << "\n"; }This prints
SELECT * FROM users WHERE age > 18. In aconstmember functionthispoints to const.What is the difference between a function pointer and
std::function?A function pointer holds the address of one function and carries no state; a captureless lambda converts to one.
std::function<R(Args...)>is a type-erased wrapper that stores any callable with that signature: functions, capturing lambdas, functors.C++#include <functional> #include <iostream> using namespace std; int twice(int x) { return 2 * x; } int main() { int (*fp)(int) = twice; fp = [](int x) { return x + 1; }; // a captureless lambda converts function<int(int)> f = twice; cout << fp(5) << " " << f(5) << " "; int offset = 100; f = [offset](int x) { return x + offset; }; // a capturing one only fits here cout << f(5) << "\n"; }It prints
6 10 105. The flexibility costs an indirect call that rarely inlines and possibly a heap allocation for large captures, and calling an emptystd::functionthrowsstd::bad_function_call. For a callback used on the spot, a template parameter (template <class F> void each(F f)) is faster.Why can a
const&bind to a temporary, and how long does the temporary live?Binding a temporary directly to a
const T&(or aT&&) extends the temporary's life to the reference's scope, soconst std::string& s = makeName();is safe. A plainT&cannot bind to a temporary at all.C++#include <iostream> #include <string> using namespace std; struct Noisy { string name; explicit Noisy(string n) : name(n) { cout << "make " << name << "\n"; } ~Noisy() { cout << "destroy " << name << "\n"; } }; Noisy make(string n) { return Noisy(n); } int main() { const Noisy& kept = make("kept"); // lives as long as the reference make("temp"); // destroyed at the end of this line cout << "using " << kept.name << "\n"; }It prints
make kept,make temp,destroy temp,using kept,destroy kept. The extension applies only to that direct binding: a function returning aconst std::string&to a local dangles, and so doesconst auto& n = makeObj().name();whenname()returns a reference into the temporary.
C++ Pointers and References Interview Questions
Pointer arithmetic, references, const with pointers, nullptr and dangling pointers.
10 questions