C ++ rvalue reference and move

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 value
  • X&& &&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 funcit, check the parameter type
  • If the call is legal
    • If it funcis 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)

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 externand 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);
Published 74 original articles · Like 11 · Visits 30,000+

Guess you like

Origin blog.csdn.net/yijiull/article/details/89395424