Disclaimer: “this article is a summary of key reading points for chapters 1-16 of C++ Primer Chinese version (fifth edition). The original book is more detailed, this article is only for learning exchange use, unauthorized reprint is prohibited.”

If you reply to C++ on Jacen technical notes, you can get a PDF of 20,000 words C++ Primer essentials.

Chapter 1 Beginning

1.1 write a simple C++ program

int main(a)
{
	return 0;
}
Copy the code

Every C++ program contains one or more functions, one of which must be named main.

1.2 Understanding input and output

object use
cin The standard input
cout The standard output
cerr The standard error
clog Output run-time generic messages

1.3 Introduction to Notes

Two:

Single-line comment: //

Delimiters: /* and */

1.4 the control flow

while; for; if;

Chapter 2 Variables and Basic types

P30-P71

Data types are the foundation of programs. The C++ language supports a wide range of data types.

Basic built-in types

The arithmetic types

type The minimum size
bool undefined
char eight
w_char_t 16
char16_t 16
char32_t 32 –
short 16
int 16
long 32 –
long long A 64 – bit
float Six significant digits
double Ten significant digits
long double Ten significant digits

Type conversion

Do not mix signed and unsigned types.

variable

Variable definitions

(1) Basic form:

A type specifier, followed by a list of one or more variable names separated by commas and terminated with a semicolon.

(2) Initial value

In C++, initialization and assignment are two completely different operations. Initialization means assigning an initial value to a variable when it is created. Assignment means erasing the current value of an object and replacing it with a new value. The difference is small.

(3) List initialization

The way variables are initialized with curly braces is called list initialization.

(4) Default initialization

If the definition variable does not specify an initial value, the variable is initialized by default.

::: tip

Exceptions:

Variables of built-in type defined inside the function body are not initialized and their value is undefined.

It is recommended that variables of each built-in type be initialized. : : :

The relationship between variable declarations and definitions

Variable declaration: Specifies the type and name of a variable.

Variable definition: In addition to declaration, storage space needs to be applied.

If you want to declare a variable instead of defining it, use the extern keyword.

extern int i;    // Declare I instead of defining I
int j;           // Declare and define j
Copy the code

The ::: tip variable can only be defined once, but can be declared multiple times. : : :

Scope of the name

Scope: most scopes in C++ are delimited with curly braces.

Scope Once a name has been declared, all of its nested scopes have access to that name. It also allows inner scopes to redefine names in outer scopes.

::: warning If a function may use a global variable, you should not define a local variable with the same name. : : :

The compound type

Definition:

Compound types are types defined based on other types.

reference

Reference: Give the object another name.

::: Warning reference must be initialized. A reference itself is not an object, so a reference to a reference cannot be defined. References are strictly matched to the bound object. The initial value of the reference type must be an object. : : :

Pointer to the

Pointer: Is itself an object. Pointer assignment and copy are allowed. Pointers need not be assigned at definition time.

(1) Use Pointers to access objects

If the pointer points to an object, the dereference (*) is allowed to access the object.

(2) void* pointer

Understand the declaration of compound types

(1) Pointer to pointer

** represents a pointer to a pointer

*** represents a pointer to a pointer to a pointer

(2) A reference to a pointer

A pointer to a reference cannot be defined. But Pointers are objects, so there are references to Pointers.

Const qualifier

Definition: Const is used to define a variable whose value cannot be changed. A const object must be initialized.

::: tip

By default, const objects are only valid within files. When multiple files have const variables of the same name, it is equivalent to defining separate variables in different files.

If you want const variables to be shared between files, use extern.

: : :

(1) Const reference

Allows binding of a constant reference to an extraordinary number of objects, literals, and even a general expression.

In general, the type of a reference must be the same as the type of the object it refers to, except in the case of an expression.

(2) Pointers and const

To clarify the type, read from right to left.

(3) top-level const

Top-level const indicates that the pointer itself is a constant

Low-level const indicates that the object to which the pointer points is a constant.

(4) ConstEXPr and constant expressions

The new C++ standard allows variables to be declared as constexpr so that the compiler can verify that the value of a variable is a constant expression.

Processing type

Type the alias

Two methods are used to define type aliases:

(1) Use the keyword typedef

typedef double wages; // Wages is a synonym for double
typedef wages *p; // p is a synonym for double*
Copy the code

(2) Alias declaration

using SI = Sales_item;  // SI is a synonym for Sales_item
Copy the code

Auto type specifier: Lets the compiler infer the type of a variable from its initial value.

Decltype Type indicator: Selects and returns the data type of the operator. Just get the type, not actually evaluate the value of the expression.

Custom data structures

(1) class

Data structures are strategies and methods for organizing a set of related data elements and then using them.

Classes are usually not defined in the body of functions. To ensure that the definitions of classes are consistent across files, classes are usually defined in header files, and the name of the header file should be the same as the class name.

Header files usually contain entities that are defined once.

(2) preprocessor

#ifndef SALES_DATA_H
#define SALES_DATA_H
#endif
Copy the code

Preprocessing variable names are generally capitalized.

The term

Null pointer: a pointer with a value of 0 that is valid but does not point to any object. NullPtr is a literal constant that represents a null pointer.

Void * : can point to any nonvariable pointer type and cannot be dereferenced.

Chapter 3 Strings, Vectors, and Arrays

P74-P118

A string represents a variable-length sequence of characters. A vector holds a variable-length sequence of an object of a given type.

A using declaration for the namespace

using namespace:name;
Copy the code

The header file should not contain a USING declaration.

Library type String

#include <string>
using namespace std;
Copy the code

(1) Definition and initialization

string s1;
sting s2(s1);
string s3("value");
string s3 = "value";
string s4(n, 'c');
Copy the code

(2) String operations

s.empty(); / / to empty s.s considering (); // number of characters s[n]; // reference s1+s2 to the NTH character in s; // s1 and S2 connect <,<=,>,>= // compareCopy the code

::: warning

The Standards bureau allows literal and string literals to be converted to string objects. Literals and strings are different types.

: : :

(3) Handle characters in string objects

::: tip C++ program headers should use cname instead of name.h :::

Iterate over each value in a given sequence to perform some kind of operation

for (declaration : expression)
    statement
Copy the code

The library type vector

A library vector represents a collection of objects, all of which are of the same type.

Vector is a class template, not a type.

(1) Define and initialize vector

vector<T> v1;
vector<T> v2(v1);
vector<T> v2 = v1;
vector<T> v3(n, val);
vector<T> v4(n); vector<T> v5{a,b,c... } vecrot<T> v5={a,b,c... }Copy the code

If parentheses are used, the supplied values are used to construct a vector.

If we use curly braces, we initialize the vector with a list.

(2) Add elements to vector

Start by defining an empty vector to which push_back is used at run time.

(3) Other vector operations

v.empty(a); v.size(a); v.push_back(t);
v[n];
Copy the code

::: warning

Subscripts can only be performed on elements that are confirmed to exist.

: : :

Introduction to iterators

Iterator operator

*iter            // Dereference, return reference
iter->mem        // equivalent to (*iter).mem++iter --iter iter1 == iter2 iter1 ! = iter2 iter + n iter - n iter += n iter -= n iter1 - iter2// The result of subtracting two iterators is the distance between them>, > =, <, < =// Position comparison
Copy the code

::: warning

Any loop body that uses an iterator cannot add elements to the container to which the iterator belongs.

: : :

An array of

(1) Array, pointer

When we use an array subscript, we usually define it as size_t.

::: warning

Defining an array must specify the type of the array. Auto inference is not allowed.

No array of references exists.

If two Pointers point to unrelated objects, they cannot be compared.

: : :

Multidimensional array

A multidimensional array is really an array of arrays.

size_t cnt = 0;
for(auto &row : a)
	for (auto &col : row){
		col = cnt;
		++cnt;
	}
Copy the code
int *ip[4];    // An array of integer Pointers
int (*ip)[4];  // Point to an array of 4 integers
Copy the code

The term

Begin string and vector members that return an iterator to the first element. Also a library function that takes an array and returns a pointer to the first element of the array.

A member of the end string and vector that returns a trailing iterator. Also a library function that takes an array and returns a pointer to the next element at the end of the array.

Chapter 4 Expressions

P120-P151

4.1 basis

Overloaded operators: Add another layer of meaning to existing operators.

Lvalue, rvalue:

When an object is used as a right value, the value (content) of the object is used.

When an object is used as a left value, the object’s identity (its location in memory) is used.

4.2 Arithmetic operators

% : The operand must be an integer.

4.3 Logical and relational operators

The operator
!
<
< =
>
> =
= =
! =
&&
||

&& operator and | | operators are first on the left side of the value of the operand to the value of the right operand.

::: warning

Do not use Boolean literals true or false when comparing unless the comparison object is a bool.

: : :

4.4 Assignment operators

Assignment operators are right associative.

Do not confuse the equality operator with the assignment operator

if (i = j)

if (i == j)
Copy the code

4.5 Increment and decrement operators

The increment operator ++

Decrement operator —

4.6 Member access Operators

Dot operators and arrow operators

n = (*p).size(a); n = p->size(a);Copy the code

4.7 Conditional operators

condition ? expression1 : expression2;
Copy the code

4.8-bit operator

The operator function usage note
~ A complementation ~expr 1 is 0,0 is 1
<< Shift to the left expr << expr2 Insert the binary bit of the value bit 0 on the right
>> Moves to the right expr1 >> expr2
& with expr1 & expr2 If both positions are 1, the result is 1, otherwise 0.
^ An exclusive or expr1 ^ expr2 If only one of the corresponding positions is 1, the result is 1; otherwise, it is 0.
| or expr1 | expr2 If there is at least one 1 bit in the corresponding position, the result is 1; otherwise, it is 0.

4.9 Sizeof operator

The sizeof operator returns the number of bytes in an expression or the name of a type. The resulting value is size_t, which is a constant expression.

sizeof (type)
sizeof expr
Copy the code

4.10 Comma operator

The comma operator contains two objects that are evaluated from left to right.

4.11 Type Conversion

Implicit conversion

Explicit conversion

Named cast

cast-name<type>(expression)

/ / cast - name is static_cast, dynamic_cast, reinterpret_cast. Const_cast
Copy the code

::: tip

Because casts interfere with normal type checking, it is recommended to avoid casts.

: : :

4.12 Operator priority table

Chapter 5 Statements

P154-P178

5.1 Simple Statements

(1) null statement

;    / / null statement
Copy the code

(2) compound statements

A compound statement is a sequence of (possibly empty) statements and declarations enclosed in curly braces. A compound statement is also called a block.

{}
Copy the code

5.2 Statement Scope

Variables defined in a control structure are visible only inside the corresponding statement and go out of scope once the statement ends.

5.3 Conditional Statements

(1) The if statement

(2) Switch statement

The case keyword and its corresponding value together are called case tags.

Case tags must be integer constant expressions.

If a case tag matches, all case branches are executed sequentially from that tag, unless the program displays a break in the process.

Dedault tag: If none of the case tags match the value of the switch expression, the program executes the statement immediately following the default tag.

5.4 Iteration Statement

(1) The while statement

while (condition)
			statement
Copy the code

(2) The traditional for statement

for (initializar; condition; expression)
		statement
Copy the code

Objects defined in the for statement are only visible in the body of the for loop.

(3) range for statement

for (declaration : expression)
		statement
Copy the code

(4) do while statement

do 
	statement
while (condition)
Copy the code

5.5 Jump Statements

break

A break can only occur inside an iteration statement or a switch statement. It is limited to terminating the statements closest to it and then executing from the first statement following those statements.

continue

The continue statement terminates the current iteration in the most recent loop and begins the next iteration immediately.

goto

The purpose of goto is to jump unconditionally from a goto statement to another statement within the same function.

It may cause control flow disorder and should not be used.

return

5.6 Try Statement Block and Exception Handling

Exception handling in C++ includes: throw expression, try statement block.

Try and catch, enclosing a sequence of statements that may throw an exception in curly braces to form a try block. The catch clause is responsible for handling exceptions thrown by code.

The throw expression statement terminates the execution of the function. Throws an exception and transfers control to the nearest catch clause that can handle the exception.

Chapter 6 Functions

P182-P225

6.1 Function Basics

(1) Parameters and arguments:

The type of the argument must match the type of the corresponding parameter.

The call to a function specifies that the number of arguments should match the number of parameters.

(2) Local objects

Variables defined inside parameters and parameter bodies are collectively referred to as local variables. They are “local” to a function and are visible only within the function’s scope. Local variables also hide other variables with the same name in the outer scope.

Automatic objects: Objects that exist only during block execution.

Local static objects: initialized the first time a program’s execution path passes through an object definition statement and will not be destroyed until the program terminates.

size_t count_calls(a)
{
	static size_t ctr = 0;
	return ++ctr;
}
Copy the code

(3) Function declaration

The three elements of a function: return type, function name, parameter type.

Functions can be declared more than once, but can only be defined once.

(4) Separate compilation

Split compilation allows you to split a program into several files, each compiled independently.

Compile -> link

6.2 Parameter Transfer

When a parameter is a reference type, its corresponding argument is passed by reference or the function is called by reference.

When an argument is copied to a parameter, such an argument is passed by value or the function is called by value.

(1) Value transmission parameters

(2) The reference is transmitted

(3) const parameters and arguments

(4) Array parameters

When you pass an array to a function, you’re actually passing a pointer to the first element of the array.

void print(const int*);
void pring(const int[]);
void print(const int[10]);
// These three functions are equivalent
Copy the code

Array reference argument: f(int (&arr)[10])

int *matrix[10];   // An array of 10 Pointers
int (*matrix)[10]; // A pointer to an array of 10 integers
Copy the code

(5) An array containing morphable parameters

initializer_list

for err_msg(initializer_list<string> li)
Copy the code

6.3 Return Type and Return Statement

Two kinds: no return value function and right return value function.

return;
return expression;
Copy the code

After the function completes, the storage space it occupies is also released.

::: warning

Error returning a reference to a local object; Returning a pointer to a local object is also an error.

: : :

6.4 Function Overloading

Overloaded functions: Functions in the same scope that have the same name but different parameter lists are called overloaded functions. (overloaded).

Two functions are not allowed to be identical in all elements except the return type.

Overloading and scope

If you declare a name in a memory scope, it hides entities with the same name declared in the outer scope.

6.5 Special Purpose Language Features

(1) Default arguments

When a function is called, the arguments are resolved by position, and the default arguments are responsible for filling in the missing tail arguments of the function call.

typedef string::size_type sz;
string screen(sz ht = 24, sz wid = 80.char background = ' ');
Copy the code

::: tip

When designing functions that have default arguments, the order of parameters needs to be set properly. Once a parameter is assigned a default value, all parameters that follow it must have default values.

: : :

(2) Inline function

Use the keyword inline to declare inline functions.

Inlining is used to optimize smaller, flow-direct, frequently called functions.

(3) Constexpr

A constExpr function is a function that can be used in a constant expression.

6.6 Function Matching

Step1: identify candidate and alternative functions.

Step2: Find the best match.

6.7 Function Pointers

Function Pointers point to functions, not objects.

void useBigger (const string &s1, const string &s2, bool pf(const string &, const string &)); Is equivalent tovoid useBigger (const string &s1, const string &s2, bool (*pf)(const string &, const string &));
Copy the code

Chapter seven class

P228-P273

The basic idea behind classes is data abstraction and encapsulation.

Abstraction is a programming technique that relies on the separation of interface and implementation.

Encapsulation enables the separation of a class’s interface from its implementation.

7.1 Defining abstract data types

(1) this

Any direct access to a class member is treated as an implicit reference to this.

std::string isbn(a) const {returnbookNo; }Copy the code

Is equivalent to

std::string isbn(a) const {return this->bookNo; }Copy the code

(2) Define member functions outside the class

The name of a member defined outside the class must contain the name of the class to which it belongs.

double Sales_data::avg_price(a) const {
	if (units_sol)
		return revenue/units_sols;
	else
		return 0;
}
Copy the code

(3) Constructor

Definition: A class controls the initialization of its objects through one or more special member functions, called constructors.

The constructor has no return type;

The constructor name is the same as the class name.

Classes control the default initialization process through a special constructor called the default constructor.

The constructors created by the compiler are called the synthesized default constructors.

::: tip

The compiler automatically generates the default constructor only if the class does not declare any constructors.

Once we define some other constructor, the class will have no default constructor unless we also define a default constructor

: : :

7.2 Access Control and Encapsulation

(1) Access control

specifier use
public Members defined by public, which define the class interface, are accessible throughout the program.
private Members defined using private can be accessed by the class’s member functions, but not by code that uses the class. The private part encapsulates the implementation details of the class.

(2) Friends

A class can allow other classes or functions to access its non-public members by making them its friends.

Identified by the friend keyword.

Friends are not members of a class and are not bound by access control levels.

::: tip

Declarations of friends only specify access permissions, not function declarations in the usual sense. You must declare a function specifically outside of its friends.

: : :

// Sales_data.h

class Sales_data {
friend Sales_data add(const Sales_data&, const Sales_data&);
friend std::ostream &print(std::ostream&, const Sales_data&);
friend std::istream &read(std::istream&, Sales_data&);
}

// nonmember Sales_data interface functions
Sales_data add(const Sales_data&, const Sales_data&);
std::ostream &print(std::ostream&, const Sales_data&);
std::istream &read(std::istream&, Sales_data&);

//Sales_data.cpp

Sales_data 
add(const Sales_data &lhs, const Sales_data &rhs)
{
	Sales_data sum = lhs;  // copy data members from lhs into sum
	sum.combine(rhs);      // add data members from rhs into sum
	return sum;
}

// transactions contain ISBN, number of copies sold, and sales price
istream&
read(istream &is, Sales_data &item)
{
	double price = 0;
	is >> item.bookNo >> item.units_sold >> price;
	item.revenue = price * item.units_sold;
	return is;
}

ostream&
print(ostream &os, const Sales_data &item)
{
	os << item.isbn() < <"" << item.units_sold << "" 
	   << item.revenue << "" << item.avg_price(a);return os;
}

Copy the code

7.3 Other features of the class

(1) Overloading member variables

Screen myScrren;
char ch = myScreen.get(a); ch = myScreen.get(0.0);
Copy the code

(2) Initialization of class data members

Class initializers must use the initializer form = or {}.

class Window_mgr{
private:
    std::vector<Screen> screens{Screen(24.80.' ')};
}
Copy the code

(3) Overloading based on const

class Screen {
public:
	// display overloaded on whether the object is const or not
    Screen &display(std::ostream &os) 
                  { do_display(os); return *this; }
    const Screen &display(std::ostream &os) const
                  { do_display(os); return *this; }}Copy the code

When an object calls display, whether that object is const determines which version of display should be called.

(3) Class type

For a class, it must be defined before we create its objects, not just declared.

(4) Friends

Friends metaclass

If a class specifies a friend class, the member functions of the friend class can access all members of that class, including non-public members.

class Screen {
	// Members of Window_mgr can access the private parts of class Screen
	friend class Window_mgr;
}
Copy the code

Make member functions friends

Class Screen {// Window_mgr::clear must be declared before Screen class friend void Window_mgr::clear(ScreenIndex); }Copy the code

7.4 Scope of a class

A class is a scope.

7.5 Exploring constructors again

(1) The initial value of the constructor is sometimes necessary

::: tip

If the member is const, reference, or belongs to a typed class that does not provide a default constructor. We must provide initial values for these members through the constructor initializer list.

: : :

class ConstRef{
public:
	ConstRef (int i);
private:
	int i;
	const int ci;
	int &ri;
};

ConstRef:ConstRef(int ii) : i(ii), ci(ii), ri(i){  }
Copy the code

(2) The order of member initialization

Members are initialized in the same order as they appear in the class definition. P259

(3) Delegate constructor

Performs its own initialization using other constructors of the class it describes.

(4) What if the implicit conversion defined by the constructor is suppressed?

Use the explicit keyword when declaring constructors within a class.

Static member of class 7.6

(1) Declare static members

Precede the member declaration with the keyword static.

A static member of a class exists outside of any object that contains no data associated with the static member.

(2) Use static members of the class

double r;
r = Account::rate(a);Copy the code

summary

Classes have two basic abilities:

One is data abstraction, that is, the ability to define data members and function members;

The other is encapsulation, the ability to protect the members of a class from arbitrary access.

Chapter 8 IO library

P278-P290

The C++ language does not deal with input and output directly, but with IO through a set of types defined in the standard library.

  • Iostream handles console IO
  • Fstream handles named file IO
  • The stringstream completes the IO of the memory string

Ifstream and iStringstream inherit from istream

Ofstream and ostringstream inherit from ostream

8.1 the IO class

(1) The I/O object is not copied or replicated.

Functions that perform IO operations typically pass and return streams by reference.

Flush the output buffer

Flush flushes the buffer without printing any additional characters.

Ends inserts a null character into the buffer and flushes the buffer.

8.2 File INPUT and output

class role
ifstream Reads data from a given file
ofstream Writes data from a given file
fstream Reading and writing a given file

8.3 the string flow

class role
istringstream Read data from string
ostringstream Write data to string
stringstream You can either read data from a string or write data to a string
	// will hold a line and word from input, respectively
	string line, word;

	// will hold all the records from the input
	vector<PersonInfo> people;

	// read the input a line at a time until end-of-file (or other error)
	while (getline(is, line)) {       
		PersonInfo info;            // object to hold this record's data
	    istringstream record(line); // bind record to the line we just read
		record >> info.name;        // read the name
	    while (record >> word)      // read the phone numbers 
			info.phones.push_back(word);  // and store them
		people.push_back(info); // append this record to people
	}
Copy the code
	// for each entry in people
	for (vector<PersonInfo>::const_iterator entry = people.begin(a); entry ! = people.end(a); ++entry) { ostringstream formatted, badNums;// objects created on each loop

		// for each number
		for (vector<string>::const_iterator nums = entry->phones.begin(a); nums ! = entry->phones.end(a); ++nums) {if (!valid(*nums)) {           
				badNums << "" << *nums;  // string in badNums
			} else                        
				// ``writes'' to formatted's string
				formatted << "" << format(*nums); 
		}
		if (badNums.str().empty())      // there were no bad numbers
			os << entry->name << ""    // print the name 
			   << formatted.str() << endl; // and reformatted numbers 
		else                   // otherwise, print the name and bad numbers
			cerr << "input error: " << entry->name 
			     << " invalid number(s) " << badNums.str() << endl;
	}
Copy the code

Chapter 9 Sequential containers

P292-P332

Sequential containers give programmers the ability to control the order in which elements are stored and accessed.

9.1 Overview of Sequential Containers

type role
vector Variable array size. Fast random access is supported. Inserting or deleting elements outside the tail can be slow.
deque Double-endian queue. Fast random access is supported. Insertions/deletions are fast at the head and tail positions.
list Bidirectional linked lists. Only bidirectional sequential access is supported. Insert/delete operations anywhere in the list are fast.
forward_list Unidirectional linked lists. Only one-way sequential access is supported. Insert/delete operations anywhere in the list are fast.
array Fixed size array. Fast random access is supported. Elements cannot be added or removed.
string A container similar to a vector, but designed to hold characters and have fast random access. Fast insert/delete in tail.

9.2 Overview of Container Libraries

Typically, each container is defined in a header file.

Containers are defined as template classes.

Type the alias
iterator Iterator type for this container type
const_iterator You can read elements, but you cannot change the iterator type of an element
size_type An unsigned integer that is sufficient to hold the largest possible container size for this container type
difference_type A signed integer type that is sufficient to hold the distance between two iterators
value_type The element type
reference Element lvalue: has the same meaning as value_type&
const_reference The const lvalue type of the element (that is, const value_type&)
The constructor
C c; Default constructor to construct an empty container
C c1(c2) Construct a copy of C2 c1
C c(b, e) Construct C, copy elements in the range specified by iterators B and e to C (array not supported)
C c{a, b, c… } List initialization c
Assignment and swap
c1=c2 Replace elements in C1 with elements in C2
c1 = {a, b, c… } Replace elements in C1 with elements in the list (not array)
a.swap(b) Swap elements of A and B
swap(a, b) Equivalent with a.s wap (b)
The size of the
c.size() Array of elements in C (forward_list not supported)
c.max_size() The maximum number of elements that can be saved in c
c.empty() Return false if c stores elements, true otherwise
Add/Remove elements (not array)
c.insert(args) Copy the elements in ARgs into C
c.emplace(inits) Construct an element in C using inits
c.erase(args) Removes the element specified by args
c.clear() Delete all elements in c, return void
Relational operator
= =,! = All containers support equality (inequality operator)
<, < =, >, > = Relational operators (unordered associative containers are not supported)
Get iterator
c.begin(), c.end() Returns an iterator to the position after the first and last elements of C
c.cbengin(),c.cend() Returns the const_iterator
Additional members of the reverse container (forward_list not supported)
reverse_iterator Iterators that address elements in reverse order
const_reverse_iterator An element’s reverse iterator cannot be modified
c.rbegin(), c.rend() Returns an iterator to the last element of C and the position before the first element
c.crbegin(), c.crend() Return const_reverse_iterator

(1) Iterator

The library iterators allow us to access elements in a container, and all iterators do this by dereferencing operators.

An iterator return is represented by a pair of iterators that refer to the element in the same container or to the position after the last element. They mark a range of elements in the container.

Left closing range: [begin, end]

while(begin ! =end){ *begin = val; ++begin; }Copy the code

(2) Container type members

See an overview of the

Aliases allow you to use them without knowing the types of elements in the container.

(3) Begin and end members

Begin is the iterator for the first element in the container

End is the iterator for the position after the last element of the container

(4) Container definition and initialization

P290

C c;            // Default constructor
C c1(c2)
C c1=c2 C c{a,b,c... }// The list is initializedC c={a,b,c... } Cc(b,e)        // c initializes a copy of the elements in the range specified by iterators b and e
// Only the constructors of sequential containers (not array) can accept size arguments
C seq(n)
C seq(n,t)
Copy the code

Initialize one container as a copy of another:

When initializing a container as a copy of another container, both containers must have the same container type and element type.

However, when passing iterator arguments to copy a range, the container type is not required to be the same, as long as the copied elements can be converted to the element type of the container to be initialized.

Annotation library Array has a fixed size:

Built-in array types cannot be copied or assigned to objects, but arrays do not. P301

(5) Assignment and swap

The arrray type does not allow assignments from a list of values surrounded by curly braces.

array<int, 10> a2={0}; // All elements are 0
s2={0};  / / error!
Copy the code

Seq.assign (b,e) // Replaces elements in seq with elements in the range represented by iterators b and e. Iterators b and e cannot refer to elements in SEq.

Swap Is used to exchange the contents of two containers of the same type. After calling swap, the elements in the two containers will be swapped.

(6) Container size operation

Size returns the number of elements in the container

Empty Returns true if size is 0, false otherwise

Max_size returns a value greater than or equal to the maximum number of elements that a container of this type can hold

(7) Relational operators

The element objects on the left and right sides of the relational operator must be containers of the same type.

::: tip

You can use relational element conciliation to compare two containers only if the element type also defines the corresponding comparison operator

: : :

9.3 Sequential Container Operations

(1) Add elements to the sequential container

Form P305

Use push_back: to append to the container

Use push_front to insert into the container header

Add elements at specific locations in the container: use insert

vector <string> svec;
svec.insert(svec.begin(), "Hello!");
Copy the code

Insert elements in range: use insert

Using emplace operations:

Emplace_front, emplace, and emplace_back correspond to push_front, INSERT, and PUSH_back respectively.

The emplace function is constructed directly in the container, not copied.

(2) Access elements

P309

Note that end refers to the element after the last element of the container.

The operation of accessing elements in a sequential container
c.back() Returns a reference to the last element in c. If c is empty, the behavior of the function is undefined
c.front() Returns a reference to the first element in c. If c is empty, the hash behavior is undefined
c[n] Returns a reference to the element in c with subscript n, which is an unsigned integer. If n>=size(), the function behavior is undefined
c.at[n] Returns a reference to the element with subscript n. If the subscript is out of bounds, an out_of_range exception is thrown

(3) Delete elements

Sequential container deletion operation
c.pop_back() Delete the last element in c. If c is empty, the function behavior is undefined. Return void
c.pop_front() Delete the first element in c. If c is empty, the function behavior is undefined. Return void
c.erase(p) Removes the element specified by iterator p and returns an iterator that refers to the element after the deleted element. If p refers to the last element, returns an off-the-end iterator. If p is a trailing iterator, the function behavior is undefined
c.erase(b, e) Removes elements in the range specified by iterators b and e. Returns an iterator that refers to the element after the last deleted element. If e is itself a trailing iterator, then the function also returns a trailing iterator
c.claer() Delete all elements in c. Return void

Special forwar_list operation

P313

befor_begin(); cbefore_begin(); insert_after; emplace_after; erase_after;

(5) Change the container size

Reseize is used to expand or shrink containers.

The resize operation takes an optional element value parameter that initializes the elements added to the container.

If the container holds class-type elements and resize adds a new element to the container, the initial value must be provided, or the element type must provide a default constructor.

9.4 How does a vector grow

To avoid shadow performance, the library uses strategies that reduce the number of times container space is reallocated. When new memory has to be fetched, vectors and strings usually allocate more memory than is required for the new space. The container reserves this space as a spare, which can be used to hold more new elements.

Container-managed member functions:

Container size management brushes
c.shrink_to_fit() Reduce capacity() to the same size as size()
c.capacity() How many elements can C hold without reallocating memory
c.reverse() Allocate memory space that can hold at least N elements. Reverse does not change the number of elements in the container; it only affects how much memory the vector allocates in advance. Calling Reverse never reduces the memory footprint of the container.

Capcacity and size:

The difference between:

The size of the container refers to the number of elements it already holds;

Capcacity is the maximum number of elements it can hold without allocating any new memory.

Note: Allocate new memory only when you have to.

9.5 Additional String operations

(1) Other methods to construct string

Other ways to construct strings
string s(cp, n) S is a copy of the first n characters in the array pointed to by cp
string s(s2, pos2) S is a copy of string s2 starting with the subscript pos2.
string s (s2, pos2, len2) S is a copy of the len2 characters of string s2 starting with the subscript pos2

Substr operation:

The substr operation returns a string that is a partial or complete copy of the original string.

S.substr (pos, n) returns a string containing a copy of the n characters in s starting from pos. The default value of pos is 0. The default value of n is s.size() -pos, which copies all characters starting from pos

(2) Change other methods of string

Assign replaces assignment, which always replaces everything in the string

Insert to insert

Insert at the end of appEnd, always append new characters to the end of string

Replace Delete and insert

(3) String search operation

String search operation
s.find(args) Find the first occurrence of ARgs in S
s.rfind(args) Find s where args was last seen
s.find_first_of(args) Looks in s for the first occurrence of any character in args
s.find_last_of(args) Searches s for the last occurrence of any character in args
s.find_first_not_of(args) Look for the first character in S that is not in ARgs
s.find_last_not_of(args) Look for the last character in S that is not in ARgs

(4) Compare function

Compare has six versions, P327

(5) Numerical conversion

P328

tostring

stod

9.6 Container Adapter

Sequential container adapter:

stack; queue; priority_queue;

An adapter is a mechanism that makes one thing look like another.

Define an adapter:

The adapter has two constructors:

The default constructor creates an empty object

2. Accept a container constructor

Stack adapter:

The operation of the stack
s.pop() Removes the element at the top of the stack without returning its value
s.push(item) Create a new element to push to the top of the stack, either by copying or moving item, or by constructing args
s.emplace(args) By the arg structure
s.top() Returns the top element of the stack, but does not pop the element off the stack

Queue adapter:

Queue and priority_queue operations
q.pop() Returns the first element of the queue or the highest priority element of priority_queue without deleting it
q.front() q.back() Returns the first or last element, but does not delete it. This applies only to queue
q.top() Returns the highest priority element without deleting it. This applies only to priority_queue
q.push(item) q.empalce(args) Creates an element with the value item at the end of the queue or at the appropriate location in priority_queue, or constructed by args

The term

Begin Container operation: returns an iterator to the first element of the container, or a trailing iterator if the container is empty. Whether to return a const iterator depends on the type of the container.

Cbegin Container operations: Return a const_iterator after the last element of the container.

Chapter 10 generic algorithms

P336-P371

Rather than adding a lot of functionality to each container, the library provides a set of algorithms. These algorithms are generic and can be used for different types of containers and different types of elements.

10.1 an overview of the

Header files: algorithm, numeric

The algorithm does not depend on the container, but the algorithm depends on the operation of the element type.

10.2 Introduction to generic algorithms

(1) Read-only algorithm

The accumulate sum

Whether or not equal

(2) The algorithm of writing container elements

The algorithm does not check for writes

Copy algorithm: Copy

The algorithm for rearranging container elements: sort

::: tip

Library functions operate on iterators rather than containers. Therefore, the algorithm cannot add or remove elements directly

: : :

10.3 Customized Operations

The library allows us to provide our own operations in place of the default operators.

(1) Transfer function to algorithm

Predicate:

A predicate is a callable expression that returns a value that can be used as a condition.

The predicates of the library algorithm fall into two categories:

1. Unary predicates: Accept only a single parameter.

Binary predicates: take two arguments.

bool isShorter(const string &s1, const string &s2)
{
		retrun s1.size() < s2.size(a); }sort(words.begin(), words.end(), isShorter);
Copy the code

Sorting algorithm:

The stable_sort algorithm maintains the original order of equal elements.

(2) Lambda expressions

lamba:

Lambda expressions represent a callable unit of code. A lambda has a return type, a parameter list, and a function body.

[capture list](parameter list) -> return type {function body}
// capture list Captures the list of local variables defined in the lambda function
// The capture list is only used for local non-static variables. Lambda can directly use local static variables with names declared outside of their function
Lambda must use a trailing return to specify the return type
Copy the code

(3) Lambda capture and return

Two types: value capture and reference capture

::: warnning

When capturing a variable by reference, it must be guaranteed that the variable will be present when the lambda executes.

In general, you should minimize the amount of data captured to avoid potential problems.

If possible, avoid capturing Pointers or references.

: : :

Implicit capture:

When implicit and explicit capture is mixed, the first element in the capture list must be an & or =. Variables captured explicitly must be captured in a different way than those captured implicitly.

Lambda capture list P352

Variable lambda:

To change the value of a captured variable, you must add the mutable keyword at the beginning of the argument list.

Specify the lambda return type:

When you need to define a return type for a lambda, you must use a trailing return type.

(4) Parameter binding

The library bind function:

auto newCallable = bind(callable, arg_list);
// When newCallable is called, newCallable calls the callable and passes it the arguments in arg_list
Copy the code

10.4 Exploring iterators again

Insert iterators, stream iterators, reverse iterators, and move iterators

(1) Insert iterator

Back_inserter: Creates an iterator that uses push_back

Front_inserter: Creates an iterator that uses push_front

Inserter: Creates an iterator that uses inserter

(2) Iostream iterator

Istream_iterator reads the input stream

Ostream_iterator writes data to an output stream

Istream_iterator operation:

Cost – the iterator operations
istream_iterator in(is); In reads a value of type T from the input stream is
istream_iterator end; Read an istream_iterator of type T, representing the trailing position
in1 == in2 in1 ! = in2 In1 and in2 must read the same type. If they are both trailing iterators, or bound to the same input, they are equal
*in Returns the value read from the stream
in->mem It has the same meaning as (*in).mem
++in, in++ Read the next value from the input stream with >>

Ostream_iterator operation:

Ostream_iterator operation
ostream_iterator out(os); Out writes a value of type T to the output stream OS
ostream_iterator out(os, d); Out writes values of type T to the output stream OS, each followed by a d. D points to an array of characters at the end of an empty string
out = val Write val to the ostream bound to out with <<
*out, ++out, out++

(3) Reverse iterator

A reverse iterator is an iterator that moves backwards from the last element to the first element in the container.

10.5 Generic algorithm structure

Iterator category
Input iterator Read only, do not write; Single scan, incremental only
Output iterator Write, don’t read; Single scan, incremental only
Forward iterator Read/write; Multiple scans, incremental only
Bidirectional iterator Read and write, multiple scanning, can increase and decrease
Random-access iterators Read-write, multiple scan, support all iterator operations

10.6 Specific container algorithm

For list, forward_list, member function algorithms should be used in preference to generic algorithms.

The term

Cref library function: Returns a copiable object that holds a reference to a const object of a non-copiable type

Chapter 11 Associative Containers

P374-P397

Associative containers support efficient keyword lookup and access.

type note
map Associative arrays that hold keyword-value pairs
set Value holds the keyword in the container
multimap Map whose keyword can be repeated
multiset The keyword can be repeated by set
unordered_map A map organized with hash functions
unordered_set A set organized as a hash function
unordered_multimap Hash organized map; The keyword can be repeated
unordered_multiset Hash organization set; The keyword can be repeated

11.1 Using Associative Containers

A map is a collection of keyword – value pairs.

To define a map, we must specify the type of keyword and value.

// Count the number of occurrences of each word in the input
map<string, size_t> word_count;
string word;
while (cin >> word)
    ++word_count[word];
for (const auto &w : word_count)
  	count << w.first << " cccurs " < w.second 
  				<< ((w.second > 1)?" times" : "time") << endl;
Copy the code

Set is a simple collection of keywords.

To define a set, you must specify its element type.

// Count the number of occurrences of each word in the input and ignore common words
map<string, size_t> word_count;
set<string> exclude = {"the"."But"};
string word;
while (cin >> word)
		// Count only words that are not in exclude
		if (exclude.find(word) == exclude.end())
				++word_count[word]; // Get and increment the word counter
Copy the code

11.2 Overview of Associated Containers

(1) Define associated containers

When you define a map, you must specify both the keyword type and the value type.

When defining a set, you only need to specify the keyword type.

(2) Pair type

The pair library type is defined in the header utility.

A pair holds two data members. When creating a pair, you must provide two type names.

pair<string, string> anon; // Save two strings
pair<string, string> author{"James"."Joyce"}; // Initializers can also be provided for each member
Copy the code

The data type of the pair is public and the two members are named first and second.

Operation on pair, see table, P380

11.3 Associating Containers with Other Containers

Associate container with additional type aliases
key_type The keyword type for this container type
mapped_type The type associated with each keyword applies only to map
value_type For set, the same as key_type; For map, pair<const key_type, mapped_type>

(1) Associative container iterator

The iterator to set is const

The set and map keywords are const

Traverse the associative container:

Both map and SET support begin and end operations. Get the iterator using beigin, end, and then use the iterator to traverse the container.

(2) Add elements

Associative container INSERT operation
c.insert(v) V is a value_type object;
c.emplace(args) Args is used to construct an element
c.insert(b, e)
c.insert(il)
c.insert(p, v)
c.emplace(p ,args)

(3) Delete elements

Removes elements from the associated container
c.erase(k) Remove each element with the keyword k from c. Returns a size_type value indicating the number of deleted elements
c.erase(p) Removes the element specified by iterator p from c. P must refer to a real element in C and cannot be equal to C. nd(). Returns an iterator to the element after p, or.end() if p refers to the last element in c.
c.erase(b, e) Removes elements in the range represented by iterators b and e. Return to e

(4) Subscript operation of MAP

Subscript operations for map and unorder_map
c[k] Returns the element whose keyword is k; If k is not in c, initialize it by adding an element whose keyword is k
c.at[k] Access the element whose keyword is k, with parameter checking; If k is not in c, an out_of_range exception is raised

::: tip

The mapped_type object is obtained by subscripting the map. When dereferencing, the value_Type object is returned.

: : :

(5) Access elements

c.find(k)  // Return an iterator that refers to the element with the first keyword k, or a trailing iterator if k is not in the container
c.count(k)  // Returns the number of elements whose keyword is k. For containers that do not allow duplicate keywords, the return value is always 0 or 1
c.lower_bound(k)  // Return an iterator to the element whose first keyword is not less than k; Does not apply to unordered containers
c.upper_bound(k)  // Return an iterator to the element whose first keyword is greater than k; Does not apply to unordered containers
c.equal_bound(k)  // Returns an iterator pair representing the range of elements whose key is equal to k. If k does not exist, both members of a pair are equal to C.nd ().
Copy the code

11.4 Unordered Containers

Unordered containers organize elements using the keyword == operator and an object of type Hash <key_type>.

Unordered containers are stored as a set of buckets, and a hash function is applied to map elements to buckets.

Unordered container Management Operations, Tables, P395

You can also customize your own hash template P396

using SD_multiset = unordered_multiset<Sales_data, decltype(hasher)*, decltype(eqOp)*>;
SD_multiset bookStore(42, haser, eqOp);
Copy the code

Chapter 12 Dynamic Memory

P400-P436

12.1 Dynamic and Intelligent Pointers

Smart Pointers use
shared_ptr Provides a smart pointer to ownership sharing: For shared objects, it is released when the last shared_ptr pointing to it is destroyed.
unique_ptr Smart pointer that provides exclusive ownership: When unique_ptr is destroyed, the exclusive it points to is released. Unique_ptr cannot be copied or assigned directly.
weak_ptr A smart pointer to an object managed by shared_ptr. Shared_ptr does not count Weak_ptr in determining whether object view should be released.

(1) Shared_ptr class

shared_ptr<string> p1;
Copy the code

Make_shared function:

Make_shared allocates an object in dynamic memory and initializes it, returning shared_ptr for this object.

share_ptr<int> p3 = make_shared<int> (42);
Copy the code

Copy and assign to shared_ptr:

Each shareD_Ptr has an associated counter called the reference count. Once a shareD_ptr reference count reaches zero, it automatically frees its managed objects.

(2) Directly manage memory

The operator new allocates memory, and delete frees memory allocated by new.

Dynamically allocate and initialize objects using new:

// Dynamically allocated objects are initialized by default
int *pi = new int; // PI refers to a dynamically allocated, uninitialized, nameless object
Copy the code
// Direct initialization
int *pi = new int(1024); // PI points to an object with a value of 1024
Copy the code
// Initializes the value of dynamically allocated objects by following the type name with a pair of empty parentheses
int *pi1 = new int;   // The default value is initialized; * The value of pi1 is undefined
int *pi2 = new int(a);// The value is initialized to 0; * pi2 to 0
Copy the code

Dynamically allocated const objects:

const int *pci = new const int(1024);
Copy the code

Free dynamic memory:

delete p;
Copy the code

The delete expression does two things: destroys the object to which the given pointer points; Release the corresponding memory.

(3) the unique_ptr

Only one unique_ptr can point to a given object at any one time.

When unique_ptr is destroyed, the object it points to is also destroyed.

Unique_ptr operation
unique_ptr u1
unique_ptr<T, D> u2
unique_ptr<T, D> u(d)
u = nullptr
u.release()
u.reset()
u.reset(p)
u.reset(nullptr)

(4) weak_ptr

Weak + PTR is a smart pointer that does not control the lifetime of the pointed object. It points to an object managed by a shared_Ptr and does not change the shared_Ptr reference count.

Weak_ptr operation
weak_ptr w
weak_ptr w(sp)
w = p
w.reset() W blank
w.use_count() The number of shared_ptr objects shared with W
w.expired()
w.lock()

Before using Weak_ptr, you need to call lock to check whether the object that weak_ptr points to exists.

12.2 Dynamic Array

(1) New and array

The type name is followed by square brackets indicating the number of objects to be allocated.

Release dynamic array:

delete p;      // p must point to a dynamically allocated object or be null
delete [] pa;  // Pa must point to a dynamically allocated array or be null
Copy the code

Smart Pointers and dynamic arrays

unique_ptr<T []> u;
unique_ptr<T []> u(p);
u[i];
Copy the code

(2) Allocator class

The library Allocator class is defined in the memory header file to help separate memory from object construction.

allocator<string> alloc;
auto const p = alloc.allocate(n);
Copy the code
expression role
allocator[T] a Defines an Allocator object named A that allocates memory for objects of type T
a.allocate(n) Allocate a segment of raw, unconstructed memory to hold n objects of type T
a.construct(p, args) To use the memory returned by ALLOCATE, we must construct the object using Construct. When unconstructed memory is used, its behavior is undefined.
a.destroy(p) P is a pointer of type T*. This algorithm performs a destructor on the object pointed to by p

The term

New: Allocates memory from free space. New T allocates and constructs a pointer of type T. If T is an array type, new returns a pointer to the first element of the array. Similarly, new [n] T allocates n objects of type T and returns a pointer to the first element of the array.

Null dangling pointer: A pointer to memory that once held an object but has now been freed.

Smart pointer: Standard library type. Responsible for freeing memory at the right time.

Chapter 13 Copy Control

P440-P486

Five copy control operations:

Copy constructor, copy assignment operator, move constructor, move assignment operator, destructor.

The copy constructor, move constructor, defines what to do when this object is initialized with another object of the same type.

The copy assignment operators, move assignment operators define what to do when assigning an object to another object of the same type.

The destructor defines what to do when an object of this type is destroyed.

13.1 Copy, Assignment, and Destruction

(1) Copy constructor

The first argument to the copy constructor must be a reference type.

class Foo {
public :
	Foo(a);// Default constructor
	Foo(const Foo&); // Copy the constructor
}
Copy the code

Synthesized copy constructor:

If no copy constructor is defined, the compiler defines one.

Copy initialization:

Copy initialization, which requires the compiler to copy the right-hand operand into the object being created. Copy initialization is usually done using the copy constructor.

(2) Copy assignment operators

Overloaded assignment operator: oprator=

Synthetic copy assignment operator: If a class does not define its own copy assignment operator, the compiler generates a synthetic copy assignment operator for it.

(3) Destructor

Destructor: Used to release resources used by the object and destroy non-static data members of the object.

class Foo {
public:
	~Foo(a);// destructor, a class can have only one destructor.
}
Copy the code

In a destructor, there is nothing like the initializer list in a constructor to control how members are destroyed; the destructor part is implicit. Destroying a member of a class type requires execution of the member’s own destructor.

Synthesized destructor: When a class does not define its own destructor, the compiler defines a synthesized destructor for it.

The destructor body itself does not destroy members directly.

(4) The three-to-five rule

P447

Classes that require destructors also require copy and assignment operations

Classes that require copy operations also require assignment, and vice versa

(5) Use default=

Define the copy control member as =dafault to explicitly require the compiler to live to compose the version.

class Sales_data {
public:
		Sales_data(const Sales_data&) = default;
}
Copy the code

(6) Prevent copy

Add =delete to the function argument list.

=delete must occur when the function is first declared.

Destructors cannot be deleted members

The synthesized copy control member may be deleted:

If a class has data members that cannot be constructed, copied, copied, or destroyed by default, the corresponding member function is defined as deleted.

13.2 Copy Control and Resource Management

(1) Classes that behave like values

To provide the behavior of class values, each object should have a copy of itself for objects managed by the class.

Class copy assignment operator: An operation that usually combines a destructor and a constructor.

HasPtr& HasPtr::operator= (const HasPtr &rhs)
{
	auto newp = new string(*rhs.ps);
	delete ps;
	ps = newp;
	i = rhs.i;
	return *this;
}
Copy the code

(2) Classes that behave like Pointers

If you want to manage resources directly, you can use reference counting.

13.3 Switching Operations

swap

13.4 Example of Copy Control

P460

13.5 Dynamic Memory Management

P464

13.6 Object Movement

As with any assignment operator, moving an assignment operator must destroy the old state of the left-hand operand.

(1) Rvalue reference

An rvalue reference bound to an lvalue can be obtained using the move function.

int && rr3 = std::move(rr1);
Copy the code

(2) Move constructors and move assignment operators

The first argument to the move constructor is an rvalue reference to the class type.

Move assignment operator:

StrVec &StrVec::operator=(StrVec &&rhs) noexcept{}Copy the code

Synthetic movement operations:

If a class defines its own copy constructor, copy assignment operator, or destructor, the compiler does not synthesize the move constructor and move assignment operator for it.

If a class has no move operation, the class uses the corresponding copy operation instead of the move operation.

Moving iterators:

Moving the dereference operator of the iterator generates an rvalue reference.

(3) Rvalue references and member functions

::: tip

Overloaded functions that distinguish between move and copy usually have one version that accepts a const T& and another that accepts a const T&&.

: : :

Rvalues and lvalues reference member functions:

We specify the lvalue/rvalue attribute of this in the same way we define const member functions, by placing a reference qualifier after the argument list. P483

::: tip

If a member function has a reference qualifier, all versions with the same argument list must have a reference qualifier. P485

: : :

The term

Reference qualifiers: functions qualified by & can only be used with seat values; Functions qualified by && can only be used for rvalues.

Chapter 14 Overloaded operations and type conversions

P490-P523

Operator overloading redefines the meaning of the operator.

14.1 Basic Concepts

Definition: Overloaded operators are functions with special names. The name consists of an operator and a symbol. Overloaded operators contain return types, argument lists, and function bodies.

::: tip

When an overloaded operator is a member function, this is bound to the left-hand operand. The number of explicit arguments of a member operator function is one less than the number of operands.

For an operator, it is either a member of a class, or at least has an argument of a class type.

We can only overload existing operators.

: : :

Call an overloaded operator function directly

data1 + data2;
operator+(data1, data2);
// The above two calls are equivalent
Copy the code

14.2 Input and output operators

(1) Overloaded output operator <<

ostream &operator<<(ostream &os, const Sales_data &item)
{
	os << item.isbn() < <"" << item.unites_sold << "" << item.revenue << "" << item.avg_price(a);return os;
}
Copy the code

(2) Overload input operator >>

istream &operator>>(istream &is, Sales_data &item)
{
	double price;
	is >> item.bookNo >> item.units_sold >> price;
	if (is)
		item.revenue = items.units_sold * price;
	else
		item = Sales_data(a);return is;
}
Copy the code

14.3 Arithmetic and relational operators

(1) The equality operator

bool operator= = (const Sales_data &lhs, const Sales_data &rhs)
{
	return lhs.isbn() == rhs.isbn() &&
			lhs.unites_sold == rhs.units_sold &&
			lhs.revenue == rhs.revenue;
}
Copy the code

(2) Relational operators

operator<

14.4 Assignment operators

operator=

operator+=

14.5 Subscript operators

operator[]

Subscript operators must be member functions.

class StrVec{
public:
	std::string& operator[](std::size_t n){
		return elements[n];
	}
	const std::string& operator[](std::size_t n) const{
		return elements[n];
	}
private:
	std::string *elements;
}
Copy the code

14.6 Decrement and increment operators

Increment operator (++)

Decrement operator (–)

Define the pre-increment/decrement operator:

class StrBlobPtr{ public: StrBlobPtr& operator++(); StrBlobPtr& operator--(); }Copy the code

Distinguish between pre-and post-operators:

class StrBlobPtr{
public:
	StrBlobPtr operator+ + (int); // Postposition operator
	StrBlobPtr operator--(int);
}
Copy the code

14.7 Member access operators

operator*

operator->

14.8 Function call operators

If a class overloads the function call operator, we can use objects of that class as if they were functions.

struct absInt{
	int operator(a)(int val) const {
		return val < 0? -val : val; }}; absInt absObj;int ui = absObj(i);
Copy the code

Objects of this class are called function objects if call operators are defined.

14.9 Overloading, conversions, and operators

(1) Type conversion operator

A conversion operator is a special member function of a class that converts a value of one class type to another type. Form:

operator type() const;

(2) Avoid ambiguous type conversion

(3) Function matching with overloaded operators

::: warning

If you provide both a type conversion whose conversion target is arithmetic and an overloaded operator for the same class, you will encounter ambiguity between overloaded and built-in operators.

: : :

The term

Class type conversions: Conversions from other types to class types defined by constructors and conversions from class types to other types defined by type conversion operators.

Chapter 15 Object-oriented programming

P526-P575

15.1 the OOP: overview

(1) Core ideas of Object-oriented programming:

Data abstraction, inheritance, and dynamic binding.

(2) Inheritance:

Inheritance is a kind of hierarchical relationship linked together. In this relationship, the root is the base class, and the classes inherited from the base class become derived classes.

The base class is responsible for defining the members that are common to all classes in the hierarchy, while each derived class defines its own unique members.

Virtual functions: virtual functions. Base classes expect derived classes to define their own versions of functions.

class Quote {
public:
		std::string isbn(a) const;
		virtual double net_price(std::size_t n) const;
}
Copy the code

(3) Dynamic binding:

::: tip

In C++, dynamic binding (also known as runtime binding) occurs when we call a virtual function using a reference (or pointer) to a base class. P527

: : :

15.2 Defining base and derived classes

(1) Define the base class

Virtual function: a function that the base class wants to be overridden by its derived class.

The base class defines this function as virtual.

The base class causes its member functions to perform dynamic binding by prefixing the declaration statement with the keyword virtual.

The keyword virtual can only appear before declarations inside a class and cannot be used in function definitions outside the class.

If a function is declared virtual by the base class, that function is implicitly virtual in the derived class.

(2) Define derived classes

A derived class must specify which base class it inherits from through the derived class list.

class Bulk_quote : public Quote {
... / / to omit
}
Copy the code

For virtual functions in derived classes:

If a derived class does not override a virtual function in the base class, the virtual function behaves like any other ordinary member.

C++ allows derived classes to explicitly indicate virtual functions that override the base class, by adding the override keyword.

Derived objects:

A derived object contains multiple parts: children of its own defined members, and children of its base class.

Type conversions derived from base classes:

Because a derived object contains parts of its base object, a derived to base conversion can be performed implicitly.

Quote item;        / / the base class
Bulk_quote bulk;   / / a derived class
Quote *p = &item;  // p points to Quote
p = &bulk;         // p points to the Quote part of bulk
Quote &r = bulk;   // r is bound to the Quote part of the bulk.
Copy the code

Derived class constructor:

Each class controls the initialization of its own members. A derived class first initializes part of the base class and then initializes the members of the derived class in the order they are declared.

Derived classes use members of the base class:

Derived classes can access public and protected members of the base class.

::: tip

Derived objects cannot directly initialize members of the base class. Derived classes should follow the base class’s pretence of initializing members inherited from the base class by calling the base class’s constructor.

: : :

Classes used as base classes:

To use a class as a base class, it must be defined and not just declared.

A derived class contains children of its direct base class as well as children of each indirect base class.

Prevent inheritance from occurring:

The class name is followed by the keyword final.

class NoDerived final {};   // NoDerived cannot be a base class
Copy the code

(3) Type conversion and inheritance

We can bind a pointer or reference to a base class to a derived class object.

Static versus dynamic typing:

Static type: known at compile time, is the type at which a variable is declared or generated by an expression.

Dynamic type: Known only at run time, is the type of an in-memory object represented by a variable or expression.

Dynamic and static types are always the same if the expression is neither a reference nor a pointer.

There is no implicit conversion from base class to derived class:

Quote base;
Bulk_quote *bulkP = &base;    / / error!
Bulk_quote *bulkRef = base;   / / error!
Copy the code

::: warning

When we initialize or assign a base object from a derived object, only the base part of the derived object is copied, moved, or assigned, and the derived part is ignored.

: : :

15.3 virtual function

C++ polymorphism: use multiple forms of these types without worrying about their differences.

Virtual functions in derived classes:

If a derived class overrides an inherited virtual function, its parameter types must be exactly the same as those of the base function it overrides.

Final and Override specifiers:

If a function is marked with Override but does not override an existing virtual function, the compiler will report an error.

If a function is marked with final, any subsequent attempts to override the function will be an error.

Virtual functions and default arguments:

If a virtual function is called with a default argument, the value of that argument is determined by the static type of the call.

15.4 Abstract base Classes

Pure virtual functions:

Writing =0 can declare a virtual function as pure virtual. Pure virtual functions need not be defined.

You cannot provide a function body inside a class for a function that =0.

class Disc_quote : public Quote {
public:
		double net_price(std::size_t) const = 0;
}
Copy the code

Abstract base class:

Classes that contain pure virtual functions are abstract base classes.

Cannot create an abstract base class object.

15.5 Access Control and Inheritance

Protected members:

Members and friends of a derived class can access only protected members of the base part of a derived object; There are no special access rights for members of ordinary base-class objects. P543

Public, private, and protected inheritance:

Derived access specifiers have no effect on whether members (and friends) of derived classes can access members of their immediate base class.

Access to base class members is only related to access specifiers in the base class.

The purpose of derived access specifiers is to control the access rights of derived class users to base class members.

Changing accessibility of individual members:

By using a using declaration statement inside a class, we can mark out any accessible members of the direct or indirect base class of that class.

class Derived : private Base {
public:
		using Base::size;
}
Copy the code

::: tip

A derived class can only provide a using declaration for names it can access.

: : :

Default inheritance protection level:

Derived classes defined using the class keyword are privately inherited;

Derived classes defined using the struct keyword are shared inheritance.

class Base {};
struct D1 : Base {};  // Public inheritance by default
class D2 : Base {};   // Private inheritance by default
Copy the code

Class scope in 15.6 Inheritance

Name lookup at compile time:

The static type of an object, reference, or pointer determines which members of the object are visible.

Name conflicts and inheritance:

A member of a derived class hides a member of the base class with the same name.

::: tip

In addition to overriding inherited virtual functions, derived classes are better off using names defined in the base class.

: : :

If a member function of a derived class has the same name as a member function of the base class, the derived class hides that member function in its scope.

::: tip

Non-virtual functions do not bind dynamically.

: : :

15.7 Constructors and copy control

(1) Virtual destructor

Define the destructor as virtual in the base class to ensure that the correct version of the destructor is executed.

Quote *itemP = new Quote;
delete itemP;           // Call the destructor of Quote
itemP = new Bulk_quote;
delete itemP;           // Call the destructor of Bulk_quote
Copy the code

The virtual destructor prevents the synthetic move operation.

(2) Synthetic copy control and inheritance

The absence of a move operation in the base class prevents derived classes from having their own synthetic move operation, so when a move operation is actually performed, it must first be explicitly defined in the base class. P554

(3) Copy control members of derived classes

Copy or move constructors for derived classes:

::: tip

By default, the base class default constructor initializes the base part of a derived object. If we want to copy (or move) part of the base class, we must explicitly use the copy (or move) constructor of the base class in the constructor initializer list of the derived class.

: : :

Assignment operators for derived classes:

The assignment operator of a derived class must explicitly assign the base part of the class.

Destructors for derived classes:

Derived class functions are only responsible for destroying resources allocated by the derived class itself.

15.8 Containers and Inheritance

When using containers to store objects in an inheritance system, you must use indirect storage. It is not allowed to hold different types of elements in a container.

The term

If the virtual function defined in a derived class has the same parameter list as the virtual function defined in the base class, the derived class version overrides the base class version.

Polymorphism: The ability of a program to obtain type-specific behavior through the dynamic type of a reference or pointer.

Chapter 16 Templates and Generic Programming

P578-P630

(1) Control instantiation

When the compiler encounters an extern template declaration, it does not generate instantiation code in this file. Declaring an instantiation extern promises a non-extern declaration (definition) of the instantiation elsewhere in the program. There may be multiple extern declarations for a given instantiated version, but there must be only one definition.

(2) Templates are the foundation of the standard library.

The process of generating a particular class or function is called instantiation.

(3) Terminology

Class template: A template definition from which specific classes can be instantiated. The definition of a class template begins with the keyword template, followed by Angle brackets to < and >, a comma-separated list of one or more template parameters, followed by the class definition.

Function template: Template definition from which specific functions can be instantiated. The definition of a function template begins with the keyword template, followed by Angle brackets < and >, followed by a comma-separated list of one or more template arguments, followed by the definition of the function.