C++11

content

1. List initialization

2. Variable type deduction

3. Default member function control

4. rvalue reference

5. lambda expressions

6. Thread library


The introduction specifies the syntax of C++. Compared with C++98, new syntax has been added to make development more efficient, so we have to learn its new rules.

1. List initialization

In C++98, initializing array elements with curly braces {} is allowed,

int array1[] = {1,2,3,4,5};
int array2[5] = {0};

However, such initialization cannot be used for custom types or array initialization in the following way

vector<int>v{1,2,3,4,5};
int* array3 = new int[5]{1,2,3,4,5};

So C++11 implements this function.

2. Variable type deduction

What's the use of type deduction? 1. Solve the case where the actual type cannot be given. 2. The type is written out in a very complicated situation

Using the auto compiler will automatically deduce the type, which is more concise.

However, there is a precondition for the use of auto. The type declared by auto must be initialized, otherwise the compiler cannot deduce the actual type of auto.

template<class T1, class T2>//模板函数
T1 Add(const T1& left, const T2& right)
{
return left + right;
}

There is no error in using the actual type of the added result as the return value type of the function, which requires RTTI (Run-Time Type Identification).

And decltype is based on the actual type of the result as the return value type of the function.

int main()
{
  int a = 10;
  int b = 20;
  decltype(a+b)c;
  return 0;
}

3. Default member function control

Some default member functions, constructors, destructors, etc. will be generated in C++. If it is explicitly defined, the compiler will not regenerate the default function. For example, if a constructor with parameters is explicitly defined, it will not be generated without parameters. To avoid confusion, C++11 gives programmers control over whether compiler-generated functions are required.

In C++11, you can add =default to the definition or declaration of a default function, thereby explicitly instructing the compiler to generate a default version of the function. A function modified with =default is called an explicit default function .

class A
{
public:
A(int a): _a(a)
{}
A() = default;//指定函数生成
// 在类中声明,在类外定义时让编译器生成默认赋值运算符重载
A& operator=(const A& a);
private:
int _a;
};
A& A::operator=(const A& a) = default;
int main()
{
A a1(10);
A a2;
a2 = a1;
return 0;
}

In C++11, it is simpler. Just add =delete to the function declaration. This syntax instructs the compiler not to generate
the default version of the corresponding function. The function modified by =delete is called a delete function .

class A
{
public:
A(int a): _a(a)
{}
// 禁止编译器生成默认的拷贝构造函数以及赋值运算符重载
A(const A&) = delete;
A& operator(const A&) = delete;
private:
int _a;
};

4. rvalue reference

C++ proposes references. In order to improve the efficiency of program operation, C++11 introduces rvalue references. Rvalue references are also aliases, but they can only be referenced to rvalues.

int Add(int a,int b)
{
    return a + b;
}
int main()
{
    const int&& ra = 10;
    int&& rRet = Add(10,20);
    return 0;
}

There is no strict distinction between lvalues ​​and rvalues. It is generally believed that:

① can be placed on the left side of =, ② or can take an address is called an lvalue,

① can only be placed on the right side of =, ② or cannot take an address is called an rvalue.

int main()
{
    int a = 10;
    int b = 20;

    a = b;
    b = a;//a和b都是左值,左值即可放在=的左侧,也可以放在=的右侧

    b + 1 =20;//b+1的结果是一个临时变量,没有具体名称,也不能取地址,因此为右值
}

It is difficult to distinguish whether it is an lvalue or an rvalue only by the above concept, so it is generally believed that:
1. Variables of ordinary types, because they have names and can take addresses, are considered to be lvalues.
2. The const-modified constant, unmodifiable, read-only type, should be treated as an rvalue in theory, but because it can take an address (if it is only the definition of a const type constant, the compiler will not open up space for it, if the constant is taken address, the compiler only opens up space for it), C++11 considers it to be an lvalue.
3. If the result of running the expression is a temporary variable or object, it is considered an rvalue.
4. An lvalue is considered if the result of the evaluation of the expression or if a single variable is a reference.

Reference and rvalue reference comparison

int main()
{
// 普通类型引用只能引用左值,不能引用右值
int a = 10;
int& ra1 = a; // ra为a的别名
//int& ra2 = 10; // 编译失败,因为10是右值
const int& ra3 = 10;
const int& ra4 = a;
return 0;
}

Ordinary references can only refer to lvalues, not rvalues,

A const reference can refer to either an lvalue or an rvalue.

An rvalue reference can only refer to rvalues.

int main()
{
// 10纯右值,本来只是一个符号,没有具体的空间,
// 右值引用变量r1在定义过程中,编译器产生了一个临时变量,r1实际引用的是临时变量
int&& r1 = 10;
r1 = 100;
int a = 10;
int&& r2 = a; // 编译失败:右值引用不能引用左值
return 0;
}

5. lambda expressions

In C++98, to sort the elements of a data set, std::sort can be used.

int main()
{
int array[] = {4,1,8,5,3,7,0,9,2,6};
// 默认按照小于比较,排出来结果是升序
std::sort(array, array+sizeof(array)/sizeof(array[0]));
// 如果需要降序,需要改变元素的比较规则
std::sort(array, array + sizeof(array) / sizeof(array[0]), greater<int>());
return 0;
}

But with the development of C++ syntax, people began to feel that the above way of writing is too complicated, so lambda expressions came out.

lambda syntax

Lambda expression writing format: [capture-list] (parameters) mutable -> return-type { statement }

[capture-list] capture list

(parameters) parameter list

mutable: By default, a lambda function is always a const function, and mutable can cancel its constancy.

->returntype: Return value type.

{statement}: The function body.

int main()
{
// 最简单的lambda表达式, 该lambda表达式没有任何意义
[]{};
// 省略参数列表和返回值类型,返回值类型由编译器推导为int
int a = 3, b = 4;
[=]{return a + 3; };
// 省略了返回值类型,无返回值类型
auto fun1 = [&](int c){b = a + c; };
fun1(10)
cout<<a<<" "<<b<<endl;
// 各部分都很完善的lambda函数
auto fun2 = [=, &b](int c)->int{return b += a+ c; };
cout<<fun2(10)<<endl;
// 复制捕捉x
int x = 10;
auto add_x = [x](int a) mutable { x *= 2; return a + x; };
cout << add_x(10) << endl;
return 0;
}

The capture list describes the context of which data can be used by the lambda, and whether pass-by-value or pass-by-reference is used.

[var]: Indicates pass-by-value capture variables var
[=]: Indicates pass-by-value captures all variables in the parent scope (including this)
[&var]: Indicates pass-by-reference capture variables var
[&]: Indicates pass-by-reference captures all Variables in the parent scope (including this)
[this]: Indicates that the value is passed to capture the current this pointer

Function objects and lambda expressions

Function objects, also known as functors. That is, an object that can be used like a function is a class object that overloads the operator() operator in the class.

class Rate
{
public:
Rate(double rate): _rate(rate)
{}
double operator()(double money, int year)
private:
double _rate;
};
int main()
{
// 函数对象
double rate = 0.49;
Rate r1(rate);
r1(10000, 2);
// lamber
auto r2 = [=](double monty, int year)->double{return monty*rate*year; };
r2(10000, 2);
return 0;
}

6. Thread library

Function name Function
thread() Constructs a thread object without any associated thread function, that is, does not start any thread
thread(fn,args1, args2,...) Constructs a thread object and associates thread functions fn, args1, args2, . ..
Get the thread id for the parameter get_id() of the thread function
jionable() Whether the thread is still executing, joinable represents a thread that is being executed.
jion() After this function is called, the thread will be blocked. When the thread ends, the main thread will continue to execute
detach() Called immediately after the thread object is created, it is used to separate the created thread from the thread object, and the detached thread becomes Background thread, the "dead and alive" of the created thread has nothing to do with the main thread

A thread is a concept in the operating system. A thread object can be associated with a thread to control the thread and obtain the state of the thread.

int main()
{
// 线程函数为函数指针
thread t1(ThreadFunc, 10);
// 线程函数为lambda表达式
thread t2([]{cout << "Thread2" << endl; });
// 线程函数为函数对象
TF tf;
thread t3(tf);
t1.join();
t2.join();
t3.join();
cout << "Main thread!" << endl;
return 0;
}

lock_guard与unique_lock

In some cases, in order to ensure the security of a piece of code, it is necessary to control it by means of locks.

When the lock control is not good before, it may cause deadlock. C++11 uses the RAII method to encapsulate the lock, namely lock_guard and unique_lock .

In C++11, Mutex includes a total of four types of mutex:
1.std::mutex

The three most commonly used functions of mutex:
function name function function
lock() lock: lock the mutex
unlock() unlock: release the ownership of the mutex
try_lock() try to lock the mutex, if the mutex is blocked If other threads occupy it, the current thread will not be blocked

2. std::recursive_mutex

The same thread is allowed to lock the mutex multiple times (that is, recursive lock) to obtain multiple layers of ownership of the mutex object. When releasing the mutex, it needs to call unlock() with the same depth as the lock hierarchy.

3. std::timed_mutex
has two more member functions than std::mutex, try_lock_for(), try_lock_until().
try_lock_for()
accepts a time range, indicating that the thread will be blocked if it does not acquire the lock within this time range (
different from std::mutex's try_lock(), if try_lock does not acquire the lock when it is called, it will directly return false) , if another thread releases the lock during this period
, the thread can acquire the lock on the mutex, and if it times out (that is, the lock is not acquired within the specified time), it returns
false.
try_lock_until()
accepts a time point as a parameter. If the thread does not acquire the lock before the specified time point, it will be blocked. If other threads release the lock during this
period , the thread can acquire the lock on the mutex.
Returns false if it times out (that is, the lock has not been acquired within the specified time ).

4. std::recursive_timed_mutex

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324304228&siteId=291194637