Copy assignment (via operator=) can be used to assign an already created variable a value.
-Initialization can be used to give a variable a value at the point of creation. C++ supports 3 types of initialization:
Copy initialization.
Direct initialization (also called parenthesis initialization).
Brace initialization (also called uniform initialization or list initialization).
You should prefer brace initialization over the other initialization forms, and prefer initialization over assignment.
Functions and Files
A function is a reusable sequence of statements designed to do a particular job. Functions you write yourself are called user-defined functions.
A local variable’s scope begins at the point of variable definition, and stops at the end of the set of curly braces in which it is defined (or for function parameters, at the end of the function).
Practice DRY programming -- “don’t repeat yourself”. Make use of variables and functions to remove redundant code.
Function parameters and variables defined inside the function body are called local variables. The time in which a variable exists is called its lifetime. Variables are created and destroyed at runtime, which is when the program is running. A variable’s scope determines where it can be accessed. When a variable can be accessed, we say it is in scope. When it can not be accessed, we say it is out of scope. Scope is a compile-time property, meaning it is enforced at compile time.
It is worth noting that function declarations do not need to specify the names of the parameters (as they are not considered to be part of the function declaration).
所以重载的时候,名字参数名字不能作为重载的内容。
Fundamental Data Types
The sizeof operator can be used to return the size of a type in bytes.
A constant is a value that may not be changed. C++ supports two types of constants: const variables, and literals. A variables whose value can not be changed is called a constant variable. The const keyword is used to make a variable constant.
Literals are values inserted directly into the code. Literals have types, and literal suffixes can be used to change the type of a literal from the default type.
A magic number is a literal (usually a number) that either has an unclear meaning or may need to be changed later. Don’t use magic numbers in your code. Instead, use symbolic constants.
Operators
Strongly favor the prefix version of the increment and decrement operators, as they are generally more performant, and you’re less likely to run into strange issues with them.
Scope, Duration, and Linkage
Keep the nesting level of your functions to 3 or less. If your function has a need for more nested levels, consider refactoring your function into sub-functions.
-Consider using a “g” or “g_” prefix when naming non-const global variables, to help differentiate them from local variables and function parameters.
An identifier with internal linkage can be seen and used within a single file, but it is not accessible from other files
-Global variables with internal linkage are sometimes called internal variables.
Functions default to external linkage (which we’ll cover in the next lesson), but can be set to internal linkage via the static keyword:
Global variables are variables defined outside of a function. Global variables have file scope, which means they are visible from the point of declaration until the end of the file in which they are declared. Global variables have static duration, which means they are created when the program starts, and destroyed when it ends. Avoid dynamic initialization of static variables whenever possible.
An identifier’s linkage determines whether other declarations of that name refer to the same object or not. Local variables have no linkage. Identifiers with internal linkage can be seen and used within a single file, but it is not accessible from other files. Identifiers with external linkage can be seen and used both from the file in which it is defined, and from other code files (via a forward declaration).
Type Conversion and Function Overloading
Function overloading allows us to create multiple functions with the same name, so long as each identically named function has different set of parameter types (or the functions can be otherwise differentiated). Such a function is called an overloaded function (or overload for short). Return types are not considered for differentiation.
A default argument is a default value provided for a function parameter. Parameters with default arguments must always be the rightmost parameters, and they are not used to differentiate functions when resolving overloaded functions.
References and Pointers
An lvalue is an expression that evaluates to a function or an object that has an identity. An object or function with an identity has an identifier or an identifiable memory address. Lvalues come in two subtypes: modifiable lvalues are lvalues that can be modified, and non-modifiable lvalues are lvalues whose values can’t be modified (typically because they are const or constexpr).
An rvalue is an expression that is not an l-value. This includes literals (except string literals) and the return values of functions or operators (when returned by value).
A reference is an alias for an existing object. Once a reference has been defined, any operation on the reference is applied to the object being referenced.
A pointer is an object that holds a memory address (typically of another variable) as its value. This allows us to store the address of some other object to use later. Like normal variables, pointers are not initialized by default. A pointer that has not been initialized is sometimes called a wild pointer. A dangling pointer is a pointer that is holding the address of an object that is no longer valid (e.g. because it has been destroyed).
Arrays, Strings, and Dynamic Allocation
Virtual Functions
A virtual function is a special type of function that, when called, resolves to the most-derived version of the function that exists between the base and derived class. This capability is known as polymorphism. A derived function is considered a match if it has the same signature (name, parameter types, and whether it is const) and return type as the base version of the function. Such functions are called overrides.
Use the virtual keyword on virtual functions in a base class. Use the override specifier (but not the virtual keyword) on override functions in derived classes.
A virtual call is a mechanism to get work done given partial information. In particular, "virtual" allows us to call a function knowing only any interfaces and not the exact type of the object. To create an object you need complete information. In particular, you need to know the exact type of what you want to create. Consequently, a "call to a constructor" cannot be virtual.
Move Semantics and Smart Pointers
std::unique_ptr is the smart pointer class that you should probably be using. It manages a single non-shareable resource. std::make_unique() (in C++14) should be preferred to create new std::unique_ptr. std::unique_ptr disables copy semantics.
std::shared_ptr is the smart pointer class used when you need multiple objects accessing the same resource. The resource will not be destroyed until the last std::shared_ptr managing it is destroyed. std::make_shared() should be preferred to create new std::shared_ptr. With std::shared_ptr, copy semantics should be used to create additional std::shared_ptr pointing to the same object.
std::weak_ptr is the smart pointer class used when you need one or more objects with the ability to view and access a resource managed by a std::shared_ptr, but unlike std::shared_ptr, std::weak_ptr is not considered when determining whether the resource should be destroyed.