BogoToBogo
  • Home
  • About
  • Big Data
  • Machine Learning
  • AngularJS
  • Python
  • C++
  • go
  • DevOps
  • Kubernetes
  • Algorithms
  • More...
    • Qt 5
    • Linux
    • FFmpeg
    • Matlab
    • Django 1.8
    • Ruby On Rails
    • HTML5 & CSS

C++ Tutorial References for Built-in Types - 2020

cplusplus_icon.png




Bookmark and Share





bogotobogo.com site search:




Why do we need them. We have pointers....

A reference variable is actually just a pointer that reduces syntactical clumsiness related with pointers in C (reference variables are internally implemented as a pointer; it's just that programmers can't use it the way they use pointers).


As a side note, a reference must refer to some object at all times, but a pointer can point to NULL. In this way, references can be more efficient when we know that we'll always have an object to point to, because we don't have to check against NULL


void doubleRef(int &a;, int &b;)
{
	a *= 2; b *= 2;
}

void doublePtr(int *a, int *b)
{
	*a *= 2; *b *= 2;
}

int main()
{
	int x = 1, y = 10;
	doubleRef(x,y);      // 2, 20
	doublePtr(&x;, &y;);   // 4, 40
	return 0;
}



References for Built-in Types

A reference is an alias for an object. C++ reference allows us to create a new name for an existing object. It also allows us to manipulate an object in a similar way of using pointer without pointer syntax.
In practice, references are primarily used as parameters to a function such as an object passed into a function. But in this chapter we'll only deal with references for built-in types.

A reference must be initialized. Once defined, a reference cannot be made to refer to another object and this is why it must be initialized.

int ival = 128;
int &refval; = ival;	// refval is a reference to ival
int &refval2;		// Error: a reference must be initialized  	

By changing the value of reference, we can change the value of the referenced original variable. In other words, any access and modification done through the new reference affect the original.

refval++;		// ival is now 129.

Though a reference is a kind of pointer, it is not correct to initialize it to the address of an object, as we would do a pointer.

int ival = 128;
int &refval; = &ival;	// Error: refval is of type int, not int*

How about assigning a non-addressable value (such as literal constant) to the reference?

int &refval2; = 256;

Then, we'll get the error message:

error C2440: 'initializing' : cannot convert from 'int' to 'int &'
or
error: initial value of refrerence to non-const must be an lvalue

The references that we've been using so far are lvalue references-references to lvalues. The term lvalue refers to things that can be on the left side of an assignment expression such as named objects or objects allocated on the stack or heap-things with a defined storage location. The term rvalue refers to things that can occur only on the right side of an assignment expression such as literals and temporaries which are intended to never be modifiable. The lvalue references can only be bound to lvalues but not rvalues.

So, the reason why we got the error in the line

int &refval2; = 256;
is because 256 is an rvalue.

However, we can bind an rvalue to a const lvalue reference (const reference):

int const &refval2; = 256;

Note that we can also have lvalues that aren't variables:

int x;
int& getReference () 
{
        return x;
}
getReference() = 99;

Here, getReference() returns a reference to a global variablestored in a permanent location. So, we should be aware that a function call can be an lvalue if and only if the return value is a reference.

The following code compiles and produces an output for x = 0:

#include <iostream>

int main()
{
    int x = int();  // initializes x = 0
    std::cout << x << std::endl;
    return 0;
}

However, the code below does not compile because the int() is not an lvalue, and can't be assigned (no physical location to store a value):

#include <iostream>

int main()
{
    int x = int()= 99;
    std::cout << x << std::endl;
    return 0;
}

Once again, reference should be initialized via lvalue. In other words, it should be initialized via variable, not via literal value. This also applies to the pointer to a reference as shown in the code below:

int main()
{
    int x = 3;

    // ref should be initialized via variable
    // int &rx; = 3;  // Error

    int &rx; = x;     // OK

    // pointer to a reference should be initialized via pointer
    // int*& prx = &x;  // Error

    int *px = &x; 
    int *&prx; = px;     // OK

    return 0;
}

A reference almost always refers to the variable with which it was initialized. C++ references allow us to create a new name for an existing object. We can't resign a reference to refer to another variable. So, for example, the result of the code below might not be obvious:

int herWeight = 110;
int& WeightOfHermione = herWeight;
int WeightOfHarry = 170;
WeightOfHermione = WeightOfHarry;
WeightOfHarry = 200;

The line

WeightOfHermione = WeightOfHarry;
does not reassign the reference WeightOfHermione so it refers to WeightOfHarry because a reference can't be reassigned. However, because WeightOfHermione is just another name for herWeight, the code
WeightOfHermione = WeightOfHarry;
is equivalent to
herWeight = WeightOfHarry;
which assigns 170 to herWeight. The final outcome: herWeight becomes 170 and WeightOfHermione still refers to herWeight and it is 170 not 200.


Assigning an object of a different type to reference

And How about assigning an object of a different type (assuming there is a conversion from the one type to the other) to the reference?

double dval = 3.14;
int &rval3; = dval;

Again, we'll get similar error:

error C2440: 'initializing' : cannot convert from 'double' to 'int &'

This is another important feature of reference. For functions, when it is used to match arguments with parameters. With value parameters, we said that implicit type conversion occurs (the value of the argument is converted, if possible, to the data type of the parameter). In contrast, reference parameters require that the matched items must have exactly the same data type.

const reference

But things are different if it's a const reference.

int const &rval4; = 1024;
double dval = 3.14;
int const &rval5; = dval;

The conversion is done by the compiler using temporary object. This is a deliberate exception on the part of the standard, introduced before we had C++11 - value references in order to allow us to pass temporaries to functions taking references. Because this provision allows implicit conversions, we can write things like this:

void print(std::string const& s);
print("implicit_conversions - rvalue references");  

rvalue references

For rvalue references, please visit C++11 - rvalue references.


References vs. pointers

Two primary differences between a reference and pointer are:

  1. a reference must always refer to an object
  2. For pointer example:

    int *ptr = 0;
    
    Here, the pointer, ptr, currently addresses no object, but for reference,
    const int &r; = 0;
    
    internally, following takes place and the reference, r, still refers an object.
    int temp = 0;
    const int &r; = temp;
    
  3. The assignment of one reference with another changes the value of the object referenced but not the reference itself

    Following code is an example for pointers:

    int i1 = 1, i2 = 2;
    int *ptr1 = &i1;, *ptr2 = &i2;
    p1 = p2;
    
    Here, p1 and p2 now both address the same object whose value is 2. This can be a significant source of program error.
    But for references,
    #include <iostream>
    using namespace std;
    int main() 
    {
    	int i1 = 1000, i2 = 2000;
    
    	int &r1; = i1;
    	int &r2; = i2;
    
    	cout << "r1=" << r1 << " r2=" << r2 << endl;
    	cout << "&r1;=" << &r1; << " &r2;=" << &r2; << endl;
    	r1 = r2;
    	cout << "r1=" << r1 << " r2=" << r2 << endl;
    	cout << "&r1;=" << &r1; << " &r2;=" << &r2; << endl;
    }
    
    with output
    r1=1000 r2=2000
    &r1;=0017FF28 &r2;=0017FF1C
    r1=2000 r2=2000
    &r1;=0017FF28 &r2;=0017FF1C
    
    It is i1, the value referenced by r1, that is changed, and not the reference. After the assignment, the two references still refer to their original objects.

  4. Pinter Reference
    Assignment to a pointer changes the pointer's value but not the pointed-to-value. Assignment to a reference changes what the reference refers to but not the reference itself.
    Assignment of pointers does not deep copy, it just assigns to the pointer object itself. Assignment of references does deep copy, it assigns to the referred-to object.
    We cannot make a reference refer to a different object after initialization.
    To get a pointer we need to use new or &
    To access an object pointed to by a pointer, we need to use * or []

  5. Can't switch a reference to refer another.
    A reference must be initialized where it is defined. After that, it cannot be used to refer to anything else.
    char &myRef; = *(new char);
    myRef = 'x';
    delete &myRef;
    &myRef; = *(new char); Not allowed
    
  6. See also, Pointers vs References


For references with a structure and classes, please try other chapters of this tutorial.







Ph.D. / Golden Gate Ave, San Francisco / Seoul National Univ / Carnegie Mellon / UC Berkeley / DevOps / Deep Learning / Visualization

YouTubeMy YouTube channel

Sponsor Open Source development activities and free contents for everyone.

Thank you.

- K Hong






Sponsor Open Source development activities and free contents for everyone.

Thank you.

- K Hong






C++ Tutorials

C++ Home

Algorithms & Data Structures in C++ ...

Application (UI) - using Windows Forms (Visual Studio 2013/2012)

auto_ptr

Binary Tree Example Code

Blackjack with Qt

Boost - shared_ptr, weak_ptr, mpl, lambda, etc.

Boost.Asio (Socket Programming - Asynchronous TCP/IP)...

Classes and Structs

Constructor

C++11(C++0x): rvalue references, move constructor, and lambda, etc.

C++ API Testing

C++ Keywords - const, volatile, etc.

Debugging Crash & Memory Leak

Design Patterns in C++ ...

Dynamic Cast Operator

Eclipse CDT / JNI (Java Native Interface) / MinGW

Embedded Systems Programming I - Introduction

Embedded Systems Programming II - gcc ARM Toolchain and Simple Code on Ubuntu and Fedora

Embedded Systems Programming III - Eclipse CDT Plugin for gcc ARM Toolchain

Exceptions

Friend Functions and Friend Classes

fstream: input & output

Function Overloading

Functors (Function Objects) I - Introduction

Functors (Function Objects) II - Converting function to functor

Functors (Function Objects) - General



Git and GitHub Express...

GTest (Google Unit Test) with Visual Studio 2012

Inheritance & Virtual Inheritance (multiple inheritance)

Libraries - Static, Shared (Dynamic)

Linked List Basics

Linked List Examples

make & CMake

make (gnu)

Memory Allocation

Multi-Threaded Programming - Terminology - Semaphore, Mutex, Priority Inversion etc.

Multi-Threaded Programming II - Native Thread for Win32 (A)

Multi-Threaded Programming II - Native Thread for Win32 (B)

Multi-Threaded Programming II - Native Thread for Win32 (C)

Multi-Threaded Programming II - C++ Thread for Win32

Multi-Threaded Programming III - C/C++ Class Thread for Pthreads

MultiThreading/Parallel Programming - IPC

Multi-Threaded Programming with C++11 Part A (start, join(), detach(), and ownership)

Multi-Threaded Programming with C++11 Part B (Sharing Data - mutex, and race conditions, and deadlock)

Multithread Debugging

Object Returning

Object Slicing and Virtual Table

OpenCV with C++

Operator Overloading I

Operator Overloading II - self assignment

Pass by Value vs. Pass by Reference

Pointers

Pointers II - void pointers & arrays

Pointers III - pointer to function & multi-dimensional arrays

Preprocessor - Macro

Private Inheritance

Python & C++ with SIP

(Pseudo)-random numbers in C++

References for Built-in Types

Socket - Server & Client

Socket - Server & Client 2

Socket - Server & Client 3

Socket - Server & Client with Qt (Asynchronous / Multithreading / ThreadPool etc.)

Stack Unwinding

Standard Template Library (STL) I - Vector & List

Standard Template Library (STL) II - Maps

Standard Template Library (STL) II - unordered_map

Standard Template Library (STL) II - Sets

Standard Template Library (STL) III - Iterators

Standard Template Library (STL) IV - Algorithms

Standard Template Library (STL) V - Function Objects

Static Variables and Static Class Members

String

String II - sstream etc.

Taste of Assembly

Templates

Template Specialization

Template Specialization - Traits

Template Implementation & Compiler (.h or .cpp?)

The this Pointer

Type Cast Operators

Upcasting and Downcasting

Virtual Destructor & boost::shared_ptr

Virtual Functions



Programming Questions and Solutions ↓

Strings and Arrays

Linked List

Recursion

Bit Manipulation

Small Programs (string, memory functions etc.)

Math & Probability

Multithreading

140 Questions by Google



Qt 5 EXPRESS...

Win32 DLL ...

Articles On C++

What's new in C++11...

C++11 Threads EXPRESS...

Go Tutorial

OpenCV...








Contact

BogoToBogo
contactus@bogotobogo.com

Follow Bogotobogo

About Us

contactus@bogotobogo.com

YouTubeMy YouTube channel
Pacific Ave, San Francisco, CA 94115

Pacific Ave, San Francisco, CA 94115

Copyright © 2024, bogotobogo
Design: Web Master