Article Directory
Template argument inference
When passing actual parameters to a function parameter with a template type, the only types that can be automatically converted are const conversion and array or function to pointer conversion (the top-level const is ignored in formal parameters and actual parameters), arithmetic conversion, and derivative The conversion from class to base class and user-defined conversion will not work.
Trailing return type:
template <typename It>
auto func(It beg, It end) -> decltype(*beg){
return *beg;
}
An rvalue reference formal parameter can accept rvalue or lvalue, resulting in different inferences:
template <typename T>
void f(T &&){
}
int i = 0;
f(i); //如果实参是左值,则T被推导为左值引用(int&), 形参(T& &&)也折叠为左值引用(int&)
f(0); //如果实参是右值,则T被推导为(int),形参是右值引用(int &&)
The realization of move: In fact, it is to convert the lvalue to the rvalue reference, and nothing else is done.
template <typename T>
typename remove_reference<T>::type&& move(T&& t){
return static_cast<typename remove_reference<T>::type&&>(t);
}
Perfect forwarding: std::forward<T>()
return rvalue reference of T (folding may occur, return lvalue reference)
template<typename F, typename T1, typename T2>
void flip(F f, T1 &&t1, T2 &&t2){
f(std::forward<T2>(t2), std::forward<T1>(t1)); //完美保持t1和t2的属性
}
If the argument is an rvalue, then T is a common type, forward will return an rvalue reference (T &&)
If the fruit parameter is an lvalue, then T is an lvalue reference type, forward returns the rvalue reference of the lvalue reference (folded into an lvalue reference)
Folding rules :
X& &
,X& &&
,X&& &
Are folded into a left reference valueX&& &&
Collapse to rvalue reference
About rvalue references and move: https://www.zhihu.com/question/50652989
string s1 = "move";
string p = std::move(s1); //触发string的移动构造函数,s1置为空
string s2 = "not";
string&& p2 = std::move(s2); //p2只是s2的右值引用,没有除法移动构造函数,s2非空
Overload, cover, hide
Analysis process of function call in C ++ :p.func();
- First determine the static type of p
- Look in the class corresponding to the static type of p
func
. If you can't find it, continue to search along the inheritance chain to the top. If not, report an error. - After finding
func
it, check the parameter type - If the call is legal
- If it
func
is a virtual function and p is a reference or pointer, it will decide which version of the virtual function to run at runtime - Otherwise, the compiler will generate a function call (the compiler decides which to call)
- If it
Name lookup takes precedence over type checking. If a function with the same name but different parameters as the base class is found in the derived class, the base class function will still be hidden (without overloading), and the type matching will not be searched from the base class Function call.
Reference: https://www.cnblogs.com/txwsh1/archive/2008/06/28/1231751.html
The features of member functions that are overloaded
(1) The same scope (in the same class);
(2) The function name is the same;
(3) The parameters are different;
(4) The virtual keyword is optional.
Override is to assign a derived class function to overwrite a base class function, characterized by
(1) different scopes (respectively located in the derived class and the base class);
(2) the same function name;
(3) the same parameters;
(4) the base class function must have virtual keyword.
"Hidden" means that the function of the assigned class blocks the base class function with the same name. The rules are as follows
(1) If the function of the derived class has the same name as the function of the base class, but the parameters are different. At this time, regardless of the presence or absence of the virtual keyword, the functions of the base class will be hidden (not to be confused with overloading).
(2) If the function of the derived class has the same name as the function of the base class and the parameters are the same, but the base class function does not have the virtual keyword. At this time, the functions of the base class are hidden (not to be confused with coverage)
class Base{
public:
virtual int fcn();
};
class D1: public Base{
int fcn(int); //隐藏基类的fcn,不是虚函数;同时继承了Base::fcn();
virtual void f2(); //新的虚函数
};
class D2: public D1{
int fcn(int); //非虚函数,隐藏了D1::fcn(int);
int fcn(); //覆盖了Base::fcn();
void f2(); //覆盖了D1::f2();
}
Type conversion
dynamic_cast
: If the runtime information (RTTI) conversion is consistent before and after conversion, it can be converted, otherwise set nullptr (such as subclass to superclass)
static_cast
: As with c language, there is no runtime check, and the underlying const cannot be removed (error reported)
reinterpret_cast
: Provides a lower-level reinterpretation of the model of the operation object
const_cast
: Can be used to remove const and volatile
Copy constructor call timing:
- Equal sign
- Non-reference parameter
- Function non-reference return object
- List initialization structure
If the constructor is explict, you must call the constructor explicitly (you cannot rely on the copy constructor)
The compiler may change the copy initialization to direct initialization.
The copy assignment operator is called during assignment
Block copy
NoCopy() == default; //合成构造函数
Nocopy(const NoCopy&) = delete; //阻止拷贝
NoCopy &Nocopy(const NoCopy&) = delete; //阻止赋值
~NoCopy() = default; //合成析构函数
Don't return a reference or pointer on the stack
Do not return references on the heap (it is easy to cause memory leaks), such as the following example
derived& func(){
derived *d = new derived;
cout<<"func_d:"<<d<<endl;
return *d;
}
int main(){
//正确的释放内存
auto todo = &func(); //
cout<< todo <<endl;
delete todo;
//错误的
auto d = func(); //此时调用了拷贝构造函数,这时已经无法(合理的)得到func()函数中分配内存的指针了,无法释放内存
}
You can use valgrind to detect memory leaks:
valgrind --tool=memcheck --leak-check=full ./main_c
c ++ returns local variables: http://www.samirchen.com/function-returns/
Rvalue reference: https://www.cnblogs.com/tingshuo/archive/2013/01/22/2871328.html
Type conversion: https://blog.csdn.net/ydar95/article/details/69822540
Turn off RVO optimization, you can add options to g ++ -fno-elide-constructors
, otherwise the compiler will optimize the function return value and no longer create temporary objects (no longer call the copy constructor)
You can use final and override to limit or force coverage to avoid errors.
The virtual functions of the derived class will use the default arguments of the base class virtual function. Therefore, it is best to keep the default actual parameters consistent when writing the program.
The definition of a pure virtual function must be outside the class body.
About extern
and static
:
- Declare extern in the header file and define it once in a source file.
- Define static in the source file. If defined in the header file, each introduction of the header file will produce a new definition (not the same object).
Regarding pointers and references: The
compiler assigns addresses to references, but it is hidden from users.
https://stackoverflow.com/questions/57483/what-are-the-differences-between-a-pointer-variable-and-a-reference-variable-in
int x = 0;
int &r = x;
int *p = &x;
int *p2 = &r;
ssert(p == p2);