The main thing to talk about today is the features in C++11 that are rarely used in actual development. Although these features are rarely used, they brighten people's eyes and admire them after use. For example, many unnecessary functions can be written less through delegate constructors and integration constructors, and the use of final and override can enhance the readability of the code and avoid many low-level errors.
1 delegate constructor and integration constructor
1.1 delegate constructor
Delegate constructor yunxun can call another constructor in the same place. The code is as follows:
class GetNumber{ public: GetNumber(int iMax):max(iMax){} GetNumber(int iMax,int iMin):GetNumber(iMax) { min = iMin >0 && iMin<iMax? iMin:1; } GetNumber(int iMax,int iMin,int iMiddle):GetNumber(iMax,iMin) { middle = iMiddle > iMin && iMiddle < iMax ? iMiddle:2; } private: int max; int min; int middle; };
The delegate constructor should note that if the proxy constructor is used, the class member function cannot be used for initialization, but the variable assignment method should be used.
1.1 inheritance constructor
In C++11, derived functions are allowed to use the constructor of the base class, which can greatly simplify the writing of the constructor, especially when there are many constructors of the base class. The method of use is as follows:
class Base{ public: Base(int iMax):max(iMax){}; Base(int iMax,int iMin):max(iMax),min(iMin) { } Base(int iMax,int iMin,int iMiddle):max(iMax),min(iMin),middle(iMiddle) { } private: int max; int min; int middle; }; class Derived:Base{ using Base::Base; }; int main () { Derived d(1); return 0; }
As can be seen from the above code, after using the using statement in the derived class, the derived class can reduce the writing of many constructors.
2 original literal
When encoding, if you need to pass in a file path, you generally need to add an escape character to correctly represent a file path. After C++11, the original string literal "R" is added. The use of the original literal does not require special processing of the string, and the original meaning of the string will be output when outputting. Usage:
int main () { std::string str = R"test(d:\A\B\test.bat)test"; std::cout<<str; return 0; }
If the above code is output through the compiler, the output content is:
d:\A\B\test.bat
Points needing attention during use are:
- The original string must be enclosed in ()
- Strings can be added before and after parentheses, but they must be consistent on both sides of the parentheses and will not be output.
3 final and override
Similar to the java language, the final identifier indicates that the class cannot be inherited or the virtual function cannot be rewritten. The writing method is as follows:
class A { virtual void Add() final; };
If final is added to a non virtual function, an error will be reported during compilation, such as:
class A { void Add() final;//Compilation error };
The error information is as follows:
error: 'void A::Add()' marked final, but is not virtual
Similarly, if the class is defined as final:
class A final { void Add(); }; class B:A { };
The error information is as follows:
error: cannot derive from 'final' base 'A' in derived type 'B'
The override identifier can improve the readability of the code and avoid overloading the virtual function to be rewritten due to errors. The method of use is as follows:
class A { virtual void Add(); }; class B:A { void Add() override { } };
4 convenience algorithm added in C + + 11
Some convenient algorithms have been added in C++ 11. After use, the code will become more concise and convenient.
4.1 all_of,any_of,none_of
The prototypes of the three algorithms are:
template <class InputIterator, class UnaryPredicate> bool all_of (InputIterator first, InputIterator last, UnaryPredicate pred); template <class InputIterator, class UnaryPredicate> bool any_of (InputIterator first, InputIterator last, UnaryPredicate pred); template <class InputIterator, class UnaryPredicate> bool none_of (InputIterator first, InputIterator last, UnaryPredicate pred);
The three algorithms search a check interval, and the search conditions meet a unary judgment. If an element satisfies the condition, it returns true; otherwise, it returns false. The code is as follows:
int main () { std::array<int,8> foo = {1,2,4,8,16,32,64,128}; if ( std::none_of(foo.begin(), foo.end(), [](int i){return i<0;}) ) std::cout << "All numbers are not less than 0.\n"; if ( std::all_of(foo.begin(), foo.end(), [](int i){return i%2 == 0;}) ) std::cout << "All numbers are even.\n"; if ( std::any_of(foo.begin(), foo.end(), [](int i){return i%2 == 1;}) ) std::cout << "At least one number is odd.\n"; return 0; }
The running result of the code is:
All numbers are not less than 0. At least one number is odd.
4.2 find_if_not ,find_if algorithm
The function and find of the algorithm_ If on the contrary, although they can be implemented through each other, in order to improve the readability of the code without writing negative judgment during coding, a separate algorithm is added for implementation. The code usage method is as follows:
int main () { std::array<int,5> foo = {1,2,3,4,5}; std::array<int,5>::iterator it = std::find_if_not (foo.begin(), foo.end(), [](int i){return i%2;} ); std::cout << "The first even value is " << *it << '\n'; std::array<int,5>::iterator it1 = std::find_if (foo.begin(), foo.end(), [](int i){return i%2==0;} ); std::cout << "The first even value is " << *it1 << '\n'; return 0; }
As shown in the above code, the output results are the same: The first even value is 2
4.3 copy_if algorithm
Like the copy algorithm, the values in an interval are copied, but copy_if adds a condition. Only those that meet the condition will be copied_ If prototype is as follows:
template <class InputIterator, class OutputIterator, class UnaryPredicate> OutputIterator copy_if (InputIterator first, InputIterator last, OutputIterator result, UnaryPredicate pred) { while (first!=last) { if (pred(*first)) { *result = *first; ++result; } ++first; } return result; }
The method of use is as follows:
int main () { std::vector<int> foo = {1,2,3,-1,-2}; std::vector<int> bar (foo.size()); auto it = std::copy_if (foo.begin(), foo.end(), bar.begin(), [](int i){return (i<0);} ); bar.resize(std::distance(bar.begin(),it)); std::cout << "bar contains:"; for (int& x: bar) std::cout << ' ' << x; std::cout << '\n'; return 0; }
The output result of the above code is: bar contains: -1 -2.
PS: std::distance is to calculate the number of elements within the range of two iterator intervals.
4.4 iota algorithm
In the algorithm library, the algorithm can be used to generate an ordered sequence on a fixed array. The method of use is as follows:
int main () { int numbers[10]; std::iota (numbers,numbers+10,100); std::cout << "numbers:"; for (int& i:numbers) std::cout << ' ' << i; std::cout << '\n'; return 0; }
The running result of the above code is: numbers: 100 101 102 103 104 105 106 107 108 109
The running results show that the algorithm initializes the fixed length array, and the initialized value is the self increment of the third parameter.
4.5 minmax_elemen
The algorithm can obtain the maximum and minimum values in the array or container at the same time. The use method is as follows:
int main () { std::vector<int> foo {3,7,2,9,5,8,6}; auto result = std::minmax_element (foo.begin(),foo.end()); std::cout << "min is " << *result.first; std::cout << ", at position " << (result.first-foo.begin()) << '\n'; std::cout << "max is " << *result.second; std::cout << ", at position " << (result.second-foo.begin()) << '\n'; return 0; }
The running result of the above code is:
min is 2, at position 2 max is 9, at position 3
4.6 is_sorted and is_sorted_until algorithm
- is_sorted: judge whether the sequence is an ordered sequence
- is_sorted_until: returns the ordered part of the sequence
The method of use is as follows:
int main () { std::array<int,4> foo {2,4,1,3}; auto pos = std::is_sorted_until(foo.begin(),foo.end()); for(auto it =foo.begin();it != pos;it++) { std::cout<<*it<<", "; } std::cout<<std::endl; bool isSorted = std::is_sorted(foo.begin(),foo.end()); if(!isSorted) { std::cout<<"Array is not fully sorted"<<std::endl; } return 0; }
The running results of the code are as follows:
2, 4, Array is not fully sorted