update
This commit is contained in:
parent
518fa48682
commit
4f8b242a10
57
README.md
57
README.md
@ -40,7 +40,59 @@
|
||||
|
||||
#### 2.2 [C++2.0新特性](./c++2.0)
|
||||
|
||||
正在更新...
|
||||
- [Variadic Templates](variadic)
|
||||
- Spaces in Template Expressions
|
||||
|
||||
```cpp
|
||||
vector<list<int> > //ok in each C++ version
|
||||
vector<list<int>> // before c++ 11 error error: ‘>>’ should be ‘> >’ within a nested template argument list,c++11后可以正常通过
|
||||
```
|
||||
|
||||
- [nullptr and nullptr_t](nullptr.cpp)
|
||||
- [Automatic Type Deduction with auto](auto.cpp)
|
||||
- [Uniform Initialization ](uniform_initialization.cpp)
|
||||
- [initializer_list](initializer.cpp)
|
||||
- [explicit for ctors taking more than one argument]( explicit.cpp)
|
||||
- [range-based for statement](auto.cpp)
|
||||
|
||||
```cpp
|
||||
for(decl:col) {
|
||||
statement
|
||||
}
|
||||
```
|
||||
|
||||
- [=default,=delete](default_delete.cpp)
|
||||
|
||||
如果你自行定义了一个ctor,那么编译器就不会给你一个default ctor
|
||||
如果强制加上=default,就可以重新获得并使用default ctor.
|
||||
|
||||
- Alias(化名)Template(template typedef)
|
||||
|
||||
[alias.cpp](alias.cpp)
|
||||
|
||||
[template_template.cpp](template_template.cpp)
|
||||
|
||||
- [template template parameter](template_template.cpp)
|
||||
- [type alias](type_alias.cpp)
|
||||
- [noexcept](noexcept.cpp)
|
||||
- [override](override.cpp)
|
||||
- [final](final.cpp)
|
||||
- [decltype](decltype.cpp)
|
||||
- [lambda](lambda.cpp)
|
||||
- [Rvalue reference](rvalue.cpp)
|
||||
- [move aware class](move.cpp)
|
||||
- 容器-结构与分类
|
||||
|
||||
(1) 序列式容器包括:array(C++2.0新引入),vector,deque,list,forward_list(C++2.0新引入)
|
||||
|
||||
(2) 关联式容器包括:set/multiset,map/multimap
|
||||
|
||||
(3) 无序容器(C++2.0新引入,更换原先hash_xxx为unordered_xxx)包括:unordered_map/unordered_multimap,unordered_set/unordered_multiset
|
||||
|
||||
- [Hash Function](hash.cpp)
|
||||
- [tuple](tuple.cpp)
|
||||
|
||||
学习资料:https://www.bilibili.com/video/av51863195?from=search&seid=3610634846288253061
|
||||
|
||||
#### 2.3 [C++并发编程v1](./concurrency_v1)
|
||||
|
||||
@ -72,8 +124,7 @@
|
||||
|
||||
### 3.代码运行
|
||||
|
||||
代码运行:
|
||||
全部在linux下用vim编写,使用gcc/g++调试!全部可正常运行!
|
||||
全部在Ubuntu18.04下用vim编写,使用gcc/g++调试!全部可正常运行!
|
||||
|
||||
## 关于作者:
|
||||
|
||||
|
68
c++2.0/README.md
Normal file
68
c++2.0/README.md
Normal file
@ -0,0 +1,68 @@
|
||||
## C++ 2.0新特性
|
||||
|
||||
- [Variadic Templates](variadic)
|
||||
|
||||
- Spaces in Template Expressions
|
||||
|
||||
```cpp
|
||||
vector<list<int> > //ok in each C++ version
|
||||
vector<list<int>> // before c++ 11 error error: ‘>>’ should be ‘> >’ within a nested template argument list,c++11后可以正常通过
|
||||
```
|
||||
|
||||
- [nullptr and nullptr_t](nullptr.cpp)
|
||||
|
||||
- [Automatic Type Deduction with auto](auto.cpp)
|
||||
|
||||
- [Uniform Initialization ](uniform_initialization.cpp)
|
||||
|
||||
- [initializer_list](initializer.cpp)
|
||||
|
||||
- [explicit for ctors taking more than one argument]( explicit.cpp)
|
||||
|
||||
- [range-based for statement](auto.cpp)
|
||||
|
||||
```cpp
|
||||
for(decl:col) {
|
||||
statement
|
||||
}
|
||||
```
|
||||
|
||||
- [=default,=delete](default_delete.cpp)
|
||||
|
||||
如果你自行定义了一个ctor,那么编译器就不会给你一个default ctor
|
||||
如果强制加上=default,就可以重新获得并使用default ctor.
|
||||
|
||||
- Alias(化名)Template(template typedef)
|
||||
|
||||
[alias.cpp](alias.cpp)
|
||||
|
||||
[template_template.cpp](template_template.cpp)
|
||||
|
||||
- [template template parameter](template_template.cpp)
|
||||
|
||||
- [type alias](type_alias.cpp)
|
||||
|
||||
- [noexcept](noexcept.cpp)
|
||||
- [override](override.cpp)
|
||||
- [final](final.cpp)
|
||||
- [decltype](decltype.cpp)
|
||||
|
||||
- [lambda](lambda.cpp)
|
||||
|
||||
- [Rvalue reference](rvalue.cpp)
|
||||
|
||||
- [move aware class](move.cpp)
|
||||
|
||||
- 容器-结构与分类
|
||||
|
||||
(1) 序列式容器包括:array(C++2.0新引入),vector,deque,list,forward_list(C++2.0新引入)
|
||||
|
||||
(2) 关联式容器包括:set/multiset,map/multimap
|
||||
|
||||
(3) 无序容器(C++2.0新引入,更换原先hash_xxx为unordered_xxx)包括:unordered_map/unordered_multimap,unordered_set/unordered_multiset
|
||||
|
||||
- [Hash Function](hash.cpp)
|
||||
|
||||
- [tuple](tuple.cpp)
|
||||
|
||||
学习自侯捷C++11标准
|
20
c++2.0/alias.cpp
Normal file
20
c++2.0/alias.cpp
Normal file
@ -0,0 +1,20 @@
|
||||
//
|
||||
// Created by light on 19-11-3.
|
||||
//
|
||||
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
|
||||
// 不可以对alias template做偏特化或全特化
|
||||
template<typename T>
|
||||
using Vec=vector<T, allocator<T>>; // alias template using新用法
|
||||
//# define Vec<T> template<typename T> vector<T, allocator<T>> // 使用宏不行
|
||||
|
||||
int main() {
|
||||
Vec<int> col;
|
||||
// 如果使用宏上述会被替换为template<typename int> vector<int, allocator<int>> error 不是我们想要的
|
||||
// typedef vector<int, allocator<int>> Vec; // typedef也无法做到,没法指定模板参数
|
||||
|
||||
return 0;
|
||||
}
|
105
c++2.0/auto.cpp
Normal file
105
c++2.0/auto.cpp
Normal file
@ -0,0 +1,105 @@
|
||||
//
|
||||
// Created by light on 19-11-2.
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
|
||||
using namespace std;
|
||||
|
||||
// iterator stl_iterator.h里面的源码 使用auto
|
||||
template<typename _Iterator>
|
||||
#if __cplusplus < 201103L
|
||||
inline typename reverse_iterator<_Iterator>::difference_type
|
||||
operator-(const reverse_iterator<_Iterator>& __x,
|
||||
const reverse_iterator<_Iterator>& __y)
|
||||
#else
|
||||
inline auto
|
||||
operator-(const reverse_iterator<_Iterator> &__x,
|
||||
const reverse_iterator<_Iterator> &__y)
|
||||
-> decltype(__x.base() - __y.base())
|
||||
#endif
|
||||
{ return __y.base() - __x.base(); }
|
||||
|
||||
|
||||
// auto 关键字(c++11) 语法糖
|
||||
// for 循环 ranged-base for
|
||||
|
||||
|
||||
|
||||
class C {
|
||||
public:
|
||||
explicit C(const string &s) : mystr(s) {
|
||||
|
||||
}
|
||||
|
||||
friend ostream &operator<<(ostream out, const C &c) {
|
||||
out << c.mystr << endl;
|
||||
}
|
||||
|
||||
private:
|
||||
string mystr;
|
||||
};
|
||||
|
||||
int main() {
|
||||
|
||||
auto i = 42; // 编译器具备实参推导
|
||||
|
||||
auto ll1 = [](int x) -> int {
|
||||
return x + 10;
|
||||
};
|
||||
// lambda 匿名函数
|
||||
function<int(int x)> ll = [](int x) -> int {
|
||||
return x + 10;
|
||||
};
|
||||
|
||||
cout << ll(10) << endl;
|
||||
list<int> l{1, 2, 3};
|
||||
list<int>::iterator iterator;
|
||||
iterator = find(l.begin(), l.end(), 10);
|
||||
|
||||
auto ite = find(l.begin(), l.end(), 11); // auto 关键字
|
||||
|
||||
vector<int> vec;
|
||||
//=====================range-based for statement=========================
|
||||
// (1)
|
||||
for (auto elem:vec) // pass by value
|
||||
cout << elem << endl;
|
||||
// c++2.0 之前 (2) 编译器会把(1)转换为(2)或(3)
|
||||
for (auto _pos = l.begin(), _end = l.end(); _pos != _end; ++_pos)
|
||||
cout << *_pos << " ";
|
||||
cout << endl;
|
||||
// (3)
|
||||
// c++2.0之后 全局函数begin(container)与end(container) 可以接受容器
|
||||
for (auto _pos = begin(l), _end = end(l); _pos != _end; ++_pos)
|
||||
cout << *_pos << " ";
|
||||
cout << endl;
|
||||
|
||||
// (4)
|
||||
for (auto &elem:vec) // pass by reference
|
||||
elem *= 3;
|
||||
|
||||
// (5) 编译器会把(4)转换为(5)
|
||||
for (auto _pos = l.begin(), _end = l.end(); _pos != _end; ++_pos) {
|
||||
auto &elem = *_pos;
|
||||
elem *= 3;
|
||||
}
|
||||
cout << endl;
|
||||
|
||||
vector<string> vs = {"hello", "world"};
|
||||
// 加了explicit就不能转了 error
|
||||
// for (const C &elem:vs) {
|
||||
// }
|
||||
// auto 不利:降低代码可读性、可能得不到你预想的类型、配合decltype有意想不到的结果
|
||||
// auto可能得不到你预想的类型,如vector<bool>[]的返回类型。
|
||||
vector<bool> v(true);
|
||||
auto var = v.at(0);
|
||||
cout<< typeid(var).name()<<endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
36
c++2.0/constexpr.cpp
Normal file
36
c++2.0/constexpr.cpp
Normal file
@ -0,0 +1,36 @@
|
||||
//
|
||||
// Created by light on 19-11-4.
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
#include <array>
|
||||
using namespace std;
|
||||
|
||||
// 对于修饰Object来说:
|
||||
// const并未区分出编译期常量和运行期常量
|
||||
// constexpr限定在了编译期常量
|
||||
// constexpr作用:优化!效率!
|
||||
// constexpr修饰的函数,返回值不一定是编译期常量。It is not a bug, it is a feature.
|
||||
// const修饰的是类型,constexpr修饰的是用来算出值的那段代码。
|
||||
/**
|
||||
* constexpr修饰的函数,简单的来说,如果其传入的参数可以在编译时期计算出来,那么这个函数就会产生编译时期的值。
|
||||
* 但是,传入的参数如果不能在编译时期计算出来,那么constexpr修饰的函数就和普通函数一样了。不
|
||||
* @param i
|
||||
* @return
|
||||
*/
|
||||
constexpr int foo(int i)
|
||||
{
|
||||
return i+10;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int i = 10;
|
||||
std::array<int, foo(2)> arr; // OK
|
||||
|
||||
foo(i); // Call is Ok
|
||||
|
||||
std::array<int, foo(i)> arr1; // error: the value of ‘i’ is not usable in a constant expression
|
||||
|
||||
}
|
||||
|
52
c++2.0/decltype.cpp
Normal file
52
c++2.0/decltype.cpp
Normal file
@ -0,0 +1,52 @@
|
||||
//
|
||||
// Created by light on 19-11-3.
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
using namespace std;
|
||||
|
||||
// 1.used to declare return tyoes 返回类型
|
||||
|
||||
// c++2.0之前编译不出来
|
||||
//template<typename T1, typename T2>
|
||||
//decltype(x + y) add(T1 x, T2 y);
|
||||
|
||||
// 编译器编不出来在2.0之后变成下面这个,先用auto暂定,后面返回类型为decltype(x+y)
|
||||
template<typename T1, typename T2>
|
||||
auto add(T1 x, T2 y) -> decltype(x + y) { // -> 也用在lambda
|
||||
return x + y;
|
||||
}
|
||||
|
||||
class Person {
|
||||
public:
|
||||
string firstname;
|
||||
string lastname;
|
||||
};
|
||||
int main() {
|
||||
|
||||
// 1.used to declare return tyoes
|
||||
cout << add(1, 2) << endl;
|
||||
|
||||
// 2.模板元编程 例如在一个模板函数或类获取容器的value_type,这里就不封装了,直接写在main函数里面
|
||||
// 获得表达式的type 有点像typeof()特点
|
||||
map<string, float> coll;
|
||||
// 获取上述类型
|
||||
decltype(coll)::value_type m{"as", 1}; // value_type为pair<string,int> m
|
||||
cout << m.first << " " << m.second << endl;
|
||||
pair<string, int> p{"a", 2};
|
||||
cout << p.first << " " << p.second << endl;
|
||||
// 3.used to pass the type of a lambda
|
||||
|
||||
// 比大小
|
||||
auto cmp = [](const Person &p1, const Person &p2) {
|
||||
return p1.lastname< p2.lastname;
|
||||
};
|
||||
|
||||
// 对于lambda,我们往往只有object,很少有人能够写出它的类型,而有时就需要知道它的类型,要获得其type,就要借助其decltype
|
||||
set<Person, decltype(cmp)> col(cmp);
|
||||
|
||||
return 0;
|
||||
}
|
107
c++2.0/default_delete.cpp
Normal file
107
c++2.0/default_delete.cpp
Normal file
@ -0,0 +1,107 @@
|
||||
//
|
||||
// Created by light on 19-11-3.
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
#include <complex>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class Zoo {
|
||||
|
||||
public:
|
||||
Zoo(int a, int b) : a(a), b(b) {
|
||||
cout << "with param ctor \n";
|
||||
}
|
||||
|
||||
Zoo() = default;
|
||||
|
||||
Zoo(const Zoo &) = delete; // copy ctor
|
||||
|
||||
Zoo(Zoo &&) = default; // move ctor
|
||||
|
||||
Zoo &operator=(const Zoo &) = default; // copy assignment
|
||||
|
||||
Zoo &operator=(const Zoo &&) = delete; // move assignment
|
||||
|
||||
// 一般函数可以使用=default或=delete?
|
||||
// void fun1()= default; // error: ‘void Zoo::fun1()’ cannot be defaulted
|
||||
void fun1() = delete; // compile ok
|
||||
// 析构函数可以使用=default或=delete?
|
||||
// ~Zoo()= delete; // ok,但是造成使用Zoo object出错
|
||||
~Zoo() = default;
|
||||
|
||||
// 上述得出=delete可以使用在任何函数身上,而=default不可以使用在普通函数上
|
||||
// 上述会联想到=0,=0只能用在virtual funciton上
|
||||
|
||||
private:
|
||||
int a, b;
|
||||
};
|
||||
|
||||
class Empty {
|
||||
};
|
||||
|
||||
// 等价于 编译器给出的默认版本函数都是public且inline
|
||||
class Empty1 {
|
||||
public:
|
||||
Empty1() {}
|
||||
|
||||
Empty1(const Empty1 &rhs) {}
|
||||
|
||||
~Empty1() {}
|
||||
};
|
||||
|
||||
// no-copy
|
||||
// copy ctor与copy assignment都delete掉
|
||||
struct NoCopy {
|
||||
NoCopy() = default;
|
||||
|
||||
NoCopy(const NoCopy &) = delete;
|
||||
|
||||
NoCopy &operator=(const NoCopy &) = delete;
|
||||
|
||||
~NoCopy() = default;
|
||||
};
|
||||
|
||||
// no-dtor
|
||||
struct NoDtor {
|
||||
NoDtor() = default;
|
||||
|
||||
~NoDtor() = delete;
|
||||
};
|
||||
|
||||
// 对no-copy的改进 将copy ctor与copy assignment 放到private ,但是可以对member与friend调用
|
||||
// boost::noncopyable 就用到了PrivateCopy
|
||||
class PrivateCopy {
|
||||
private:
|
||||
PrivateCopy(const PrivateCopy &) {};
|
||||
|
||||
PrivateCopy &operator=(const PrivateCopy &) {};
|
||||
|
||||
public:
|
||||
PrivateCopy() = default;
|
||||
|
||||
~PrivateCopy() {};
|
||||
};
|
||||
|
||||
// 继承了的都拥有PrivateCopy性质
|
||||
class Foo : public PrivateCopy {
|
||||
|
||||
};
|
||||
|
||||
int main() {
|
||||
Zoo z;
|
||||
Zoo z1(1, 2);
|
||||
// Zoo z2=z; // error copy ctor delete
|
||||
z = z1;
|
||||
complex<int> a; // 内部不带指针的可以不用写 big three 没有析构 有copy ctor与copy assignmetn 都是使用=default,没有自己写
|
||||
string s; // 内部带指针的有big five
|
||||
|
||||
// NoDtor n; //error no-dtor 不能够自动delete
|
||||
// NoDtor *p=new NoDtor; // ok
|
||||
// delete p; // error no-dtor 不能够delete
|
||||
Foo foo;
|
||||
Foo foo1;
|
||||
// foo = foo1; // 继承了的都拥有PrivateCopy性质
|
||||
return 0;
|
||||
}
|
83
c++2.0/explicit.cpp
Normal file
83
c++2.0/explicit.cpp
Normal file
@ -0,0 +1,83 @@
|
||||
//
|
||||
// Created by light on 19-11-3.
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
// non-explicit-one-argument ctor
|
||||
class Fraction {
|
||||
public:
|
||||
// non-explicit-one-argument ctor 可以把别的东西转换为Fraction这种
|
||||
Fraction(int num, int den = 1) : m_numerator(num), m_denominator(den) {}
|
||||
|
||||
Fraction operator+(const Fraction &f) {
|
||||
return Fraction(this->m_numerator + f.m_numerator);
|
||||
}
|
||||
|
||||
|
||||
void getNumAndDen() {
|
||||
cout << m_numerator << " " << m_denominator << endl;
|
||||
}
|
||||
|
||||
private:
|
||||
int m_numerator; // 分子
|
||||
int m_denominator; // 分母
|
||||
};
|
||||
|
||||
// explicit-one-argument ctor
|
||||
class Fraction1 {
|
||||
public:
|
||||
// explicit-one-argument ctor 可以把别的东西转换为Fraction这种
|
||||
explicit Fraction1(int num, int den = 1) : m_numerator(num), m_denominator(den) {}
|
||||
|
||||
Fraction1 operator+(const Fraction1 &f) {
|
||||
return Fraction1(this->m_numerator + f.m_numerator);
|
||||
}
|
||||
|
||||
|
||||
void getNumAndDen() {
|
||||
cout << m_numerator << " " << m_denominator << endl;
|
||||
}
|
||||
|
||||
private:
|
||||
int m_numerator; // 分子
|
||||
int m_denominator; // 分母
|
||||
};
|
||||
|
||||
class P {
|
||||
public:
|
||||
P(int a, int b) {
|
||||
cout << "P(int a,int b)\n";
|
||||
}
|
||||
|
||||
P(int a, int b, int c) {
|
||||
cout << "non-explicit P(int a,int b,int c)\n";
|
||||
}
|
||||
explicit P(int a, int b, int c,int d) {
|
||||
cout << "explicit P(int a,int b,int c,int d)\n";
|
||||
}
|
||||
};
|
||||
|
||||
void fp(const P &) {
|
||||
|
||||
}
|
||||
|
||||
int main() {
|
||||
Fraction f(3, 5);
|
||||
Fraction ff = f + 3; // 会将3转换为(3,1) 隐式转换
|
||||
ff.getNumAndDen();
|
||||
|
||||
// 如果不想编译器进行隐式转换,可以在前面添加explicit关键字
|
||||
|
||||
// c++2.0之前explicit只禁止"存在单一实参"转换
|
||||
// c++2.0之后explicit可以进制"多个实参"转换
|
||||
// Fraction1 f1(3,5);
|
||||
// Fraction1 f2 = f1+3; // 会将3转换为(3,1) 不会隐式转换 error: no match for ‘operator+’ (operand types are ‘Fraction1’ and ‘int’)
|
||||
// f2.getNumAndDen();
|
||||
P p1 = {77, 5};
|
||||
P p2 = {77, 5, 89};
|
||||
// P p3 = {77, 5, 89,99}; //error: converting to ‘P’ from initializer list would use explicit constructor ‘P::P(int, int, int, int)’
|
||||
return 0;
|
||||
}
|
33
c++2.0/final.cpp
Normal file
33
c++2.0/final.cpp
Normal file
@ -0,0 +1,33 @@
|
||||
//
|
||||
// Created by light on 19-11-3.
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
// final关键字用于两个地方
|
||||
// 第一个用在类,用于说明该类是继承体系下最后的一个类,不要其他类继承我,当继承时就会报错。
|
||||
class Base final {
|
||||
public:
|
||||
Base() {}
|
||||
|
||||
virtual void func() {}
|
||||
};
|
||||
|
||||
class Derivered : public Base { // error: cannot derive from ‘final’ base ‘Base’ in derived type ‘Derivered’
|
||||
};
|
||||
// 第二个用在虚函数,表示这个虚函数不能再被override了,再override就会报错。
|
||||
class Base1 {
|
||||
public:
|
||||
Base1() {}
|
||||
|
||||
virtual void func() final {}
|
||||
};
|
||||
|
||||
class Derivered1 : public Base1 {
|
||||
virtual void func() {} // error: overriding final function ‘virtual void Base1::func()’
|
||||
};
|
||||
int main() {
|
||||
|
||||
}
|
78
c++2.0/hash.cpp
Normal file
78
c++2.0/hash.cpp
Normal file
@ -0,0 +1,78 @@
|
||||
//
|
||||
// Created by light on 19-11-4.
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
#include <unordered_set>
|
||||
#include <complex>
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
class Customer {
|
||||
|
||||
};
|
||||
|
||||
// 形式一 通过一个类,重载了操作符()的方式,形成了一个仿函数(函数对象)
|
||||
class CustomerHash {
|
||||
public:
|
||||
size_t operator()(const Customer &c) const {
|
||||
// return ...;
|
||||
}
|
||||
};
|
||||
|
||||
// 形式二 这个方法实际是通过指定了一个函数指针的方式来通知容器,对于这个自定义类到底应该使用哪个hash function
|
||||
size_t customer_hash_func(const Customer &t) {
|
||||
// return ...;
|
||||
}
|
||||
// 形式三 以struct hash 偏特化形式实现hash function
|
||||
namespace std { // 必须放在std里面
|
||||
template<>
|
||||
struct hash<Customer> : public __hash_base<size_t, Customer> { // 继承不继承都可以!
|
||||
size_t
|
||||
operator()(const Customer&s) const noexcept {
|
||||
// return ...;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
// 万能的HashFunction 使用variadic templates
|
||||
|
||||
// (4)
|
||||
template<typename T>
|
||||
inline void hash_combine(size_t& seed, const T& val){
|
||||
seed = std::hash<T>()(val) + 0x9e3779b9
|
||||
+ (seed << 6) + (seed >> 2);
|
||||
}
|
||||
|
||||
// (3)
|
||||
template<typename T>
|
||||
inline void hash_val(size_t& seed, const T& val){
|
||||
hash_combine(seed, val);
|
||||
}
|
||||
|
||||
// (2)
|
||||
template<typename T, typename... Types>
|
||||
inline void hash_val(size_t& seed, const T& val, const Types&... args){
|
||||
hash_combine(seed, val);
|
||||
hash_val(seed, args...);
|
||||
}
|
||||
// (1)
|
||||
template<typename... Types>
|
||||
inline size_t hash_val(const Types&... args){
|
||||
size_t seed = 0;
|
||||
hash_val(seed, args...);
|
||||
return seed;
|
||||
}
|
||||
|
||||
|
||||
int main() {
|
||||
unordered_set<Customer, CustomerHash> unorderedSet;
|
||||
unordered_set<Customer,size_t(*)(const Customer&)>custset(20,customer_hash_func);
|
||||
unordered_set<Customer> unset;
|
||||
int *p= reinterpret_cast<int *>(new Customer());
|
||||
cout<<hash_val(p)<<endl;
|
||||
|
||||
return 0;
|
||||
}
|
22
c++2.0/initializer.cpp
Normal file
22
c++2.0/initializer.cpp
Normal file
@ -0,0 +1,22 @@
|
||||
//
|
||||
// Created by light on 19-11-3.
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
using namespace std;
|
||||
|
||||
int main() {
|
||||
int i;
|
||||
int j(); // 0
|
||||
int *p;
|
||||
int *q(); // nullptr
|
||||
|
||||
// int x1{5.0}; // error:narrowing conversion
|
||||
// 编译器调用initializer_list私有构造之前,编译器准备好array(array头)与len,传递给该构造,并没有内含这个array,
|
||||
// 指针指向array,copy只是浅copy.
|
||||
// 如今所有容器都接受任意数量的值 insert()或assign() max() min()
|
||||
|
||||
cout<<max({1,2,3})<<endl; // algorithm里面的max/min
|
||||
return 0;
|
||||
}
|
224
c++2.0/lambda.cpp
Normal file
224
c++2.0/lambda.cpp
Normal file
@ -0,0 +1,224 @@
|
||||
//
|
||||
// Created by light on 19-11-3.
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
|
||||
using namespace std;
|
||||
|
||||
// [introducer](optional)mutable throwSpec->retType {}
|
||||
// mutable决定[]能够被改写 mutable throwSpec retType都是选择的,只要有一个存在就得写()
|
||||
// retType 返回类型
|
||||
// ()放参数
|
||||
// []放外面变量 passed by value or reference
|
||||
|
||||
|
||||
class UnNamedLocalFunction {
|
||||
private:
|
||||
int localVar;
|
||||
public:
|
||||
UnNamedLocalFunction(int var) : localVar(var) {}
|
||||
|
||||
bool operator()(int val) {
|
||||
return val == localVar;
|
||||
}
|
||||
};
|
||||
|
||||
class Person {
|
||||
public:
|
||||
string firstname;
|
||||
string lastname;
|
||||
};
|
||||
|
||||
class LambdaFunctor {
|
||||
public:
|
||||
LambdaFunctor(int a, int b) : m_a(a), m_b(b) {}
|
||||
|
||||
bool operator()(int n) const {
|
||||
return m_a < n && n < m_b;
|
||||
}
|
||||
|
||||
private:
|
||||
int m_a;
|
||||
int m_b;
|
||||
};
|
||||
|
||||
class X {
|
||||
private:
|
||||
int __x, __y;
|
||||
public:
|
||||
X(int x, int y) : __x(x), __y(y) {}
|
||||
|
||||
int operator()(int a) { return a; }
|
||||
|
||||
int f() {
|
||||
// 下列 lambda 的语境是成员函数 X::f
|
||||
// 对于[=]或[&]的形式,lambda 表达式可以直接使用 this 指针
|
||||
return [&]() -> int {
|
||||
return operator()(this->__x + __y); // X::operator()(this->x + (*this).y)
|
||||
// 拥有类型 X*
|
||||
}();
|
||||
}
|
||||
|
||||
|
||||
int ff() {
|
||||
return [this]() {
|
||||
return this->__x;
|
||||
}();
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
|
||||
[] {
|
||||
cout << "hello" << endl;
|
||||
}();
|
||||
|
||||
auto I = [] {
|
||||
cout << "hello" << endl;
|
||||
};
|
||||
I();
|
||||
int id = 0;
|
||||
// 先看前面的id 如果没有mutable error: increment of read-only variable ‘id’
|
||||
auto f = [id]()mutable {
|
||||
cout << "id=" << id << endl;
|
||||
++id;
|
||||
};
|
||||
id = 42;
|
||||
f(); // 0
|
||||
f(); // 1
|
||||
f(); // 2
|
||||
cout << id << endl;
|
||||
|
||||
// 上述lambda就相当于
|
||||
// class Functor {
|
||||
// private:
|
||||
// int id;
|
||||
// public:
|
||||
// void operator() {
|
||||
// cout << "id=" << id << endl;
|
||||
// ++id;
|
||||
// }
|
||||
// };
|
||||
// Functor f;
|
||||
|
||||
int id1 = 0;
|
||||
// 加不加mutable没影响,且传引用只要后面id1被修改了,就会使用修改后的值进行操作
|
||||
auto f1 = [&id1]() {
|
||||
cout << "id1=" << id1 << endl;
|
||||
++id1;
|
||||
};
|
||||
id1 = 42;
|
||||
f1(); // 42
|
||||
f1(); // 43
|
||||
f1(); // 44
|
||||
cout << id1 << endl;
|
||||
|
||||
|
||||
// 传参与返回
|
||||
int id2 = 0;
|
||||
auto f2 = [&id2](int ¶m) {
|
||||
cout << "id2=" << id2 << endl;
|
||||
++id2;
|
||||
++param;
|
||||
cout << "param=" << param << endl;
|
||||
static int x = 5;
|
||||
return id2;
|
||||
};
|
||||
int param = 1;
|
||||
f2(param);
|
||||
cout << "param=" << param << endl;
|
||||
|
||||
// [=] =表示默认以by value传递外部所有变量
|
||||
// [&] &表示默认以by reference传递外部所有变量
|
||||
auto f3 = [&]() {
|
||||
cout << "id=" << id << endl;
|
||||
cout << "id1=" << id1 << endl;
|
||||
cout << "id2=" << id2 << endl;
|
||||
cout << "param=" << param << endl;
|
||||
};
|
||||
f3();
|
||||
|
||||
// 一部分传引用,其余传值
|
||||
cout << "id=" << id << endl;
|
||||
auto f4 = [=, &id]() { // =不可以放在&id后面
|
||||
cout << "id=" << id << endl;
|
||||
id++;
|
||||
cout << "id1=" << id1 << endl;
|
||||
cout << "id2=" << id2 << endl;
|
||||
cout << "param=" << param << endl;
|
||||
};
|
||||
f4();
|
||||
|
||||
// 一部分传值,其余传引用
|
||||
cout << "id=" << id << endl;
|
||||
auto f5 = [&, id]() { // &不可以放在id后面
|
||||
cout << "id=" << id << endl;
|
||||
cout << "id1=" << id1 << endl;
|
||||
cout << "id2=" << id2 << endl;
|
||||
cout << "param=" << param << endl;
|
||||
};
|
||||
f5();
|
||||
// this 指针
|
||||
X x_(1, 2);
|
||||
cout << "x_.f()=" << x_.f() << endl; // 1+2=3
|
||||
cout << "x_.ff()=" << x_.ff() << endl; // 1
|
||||
|
||||
|
||||
|
||||
// 下面lambda函数等价于上述的UnNamedLocalFunction
|
||||
int tobefound = 5;
|
||||
auto lambda1 = [tobefound](int val) {
|
||||
return val == tobefound;
|
||||
};
|
||||
bool b1 = lambda1(5);
|
||||
UnNamedLocalFunction lambda2(tobefound);
|
||||
bool b2 = lambda2(5);
|
||||
cout << b1 << " " << b2 << endl;
|
||||
|
||||
auto ll1 = [](int x) -> int {
|
||||
return x + 10;
|
||||
};
|
||||
// lambda 匿名函数
|
||||
function<int(int x)> ll = [](int x) -> float {
|
||||
return x + 10.0;
|
||||
};
|
||||
cout<<ll(1)<<endl;
|
||||
|
||||
// decltype+lambda
|
||||
// 比大小
|
||||
function<bool(const Person&p1,const Person&p2)> cmp = [](const Person &p1, const Person &p2) {
|
||||
return p1.lastname < p2.lastname;
|
||||
};
|
||||
|
||||
|
||||
// 对于lambda,我们往往只有object,很少有人能够写出它的类型,而有时就需要知道它的类型,要获得其type,就要借助其decltype
|
||||
set<Person, decltype(cmp)> col(cmp);
|
||||
|
||||
// 要申明lambda对象的类型,可以使用template或者auto进行自动推导。
|
||||
// 如果需要知道类型,可以使用decltype,比如,让lambda函数作为关联容器或者无序容器的排序函数或者哈希函数。
|
||||
// 上面代码给出了事例(decltype的第三种用法中的事例),定义了一个lambda函数用cmp表示,用来比较Person对象的大小,传入到Set容器中去,
|
||||
// 但根据右边的set容器的定义,我们传入的不仅是cmp(构造函数),还要传入模板的cmp类型(Set内部需要声明cmp类型),
|
||||
// 所以必须使用decltype来推导出类型。
|
||||
// (如果没有向构造函数传入cmp,调用的是默认的构造函数,也就是set() : t(Compare()), 这里会报错, 现在不会出问题了!
|
||||
// 因为Compare()指的是调用默认的lambda构造函数,而lambda函数没有默认构造函数和赋值函数)
|
||||
|
||||
|
||||
vector<int> vec{5, 28, 50, 83, 70, 590, 245, 59, 24};
|
||||
int x = 30, y = 100;
|
||||
// 函数对象是很强大的,封装代码和数据来自定义标准库的行为,但需要写出函数对象需要写出整个class,这是不方便的,而且是非本地的,
|
||||
// 用起来也麻烦,需要去看怎样使用,另外编译出错的信息也不友好,而且它们不是inline的,效率会低一些(算法效率还是最重要的)。
|
||||
// vec.erase(remove_if(vec.begin(), vec.end(), LambdaFunctor(x, y)), vec.end());
|
||||
// for(auto i:vec) cout<<i<<" ";
|
||||
// cout<<endl;
|
||||
// 而lambda函数的提出解决了这个问题,简短有效清晰,上面的事例很好的说明了这个问题,用lambda要简短许多,功能一样,很直观。
|
||||
vec.erase(remove_if(vec.begin(), vec.end(), [x, y](int n) { return x < n && n < y; }), vec.end());
|
||||
for_each(vec.begin(), vec.end(), [](int i) { cout << i << " "; });
|
||||
cout << endl;
|
||||
return 0;
|
||||
|
||||
}
|
282
c++2.0/move.cpp
Normal file
282
c++2.0/move.cpp
Normal file
@ -0,0 +1,282 @@
|
||||
//
|
||||
// Created by light on 19-11-4.
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <typeinfo>
|
||||
#include <deque>
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <unordered_set>
|
||||
#include <unordered_map>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class MyStringNoMove {
|
||||
public:
|
||||
static size_t DCtor; // default-ctor
|
||||
static size_t Ctor; // ctor
|
||||
static size_t CCtor; // copy-ctor
|
||||
static size_t CAsgn; // copy-assignment
|
||||
static size_t MCtor; // move-ctor
|
||||
static size_t MAsgn; // move-assignment
|
||||
static size_t Dtor; // dtor
|
||||
private:
|
||||
char *_data;
|
||||
size_t _len;
|
||||
|
||||
void _init_data(const char *s) {
|
||||
_data = new char[_len];
|
||||
memcpy(_data, s, _len);
|
||||
_data[_len] = '\0';
|
||||
};
|
||||
public:
|
||||
MyStringNoMove() : _data(NULL), _len(0) { ++DCtor; }
|
||||
|
||||
MyStringNoMove(const char *p) : _len(strlen(p)) {
|
||||
++Ctor;
|
||||
_init_data(p);
|
||||
}
|
||||
|
||||
// copy ctor
|
||||
MyStringNoMove(const MyStringNoMove &str) {
|
||||
++CCtor;
|
||||
_init_data(str._data);
|
||||
}
|
||||
|
||||
|
||||
// copy assignment
|
||||
MyStringNoMove &operator=(const MyStringNoMove &str) {
|
||||
++CAsgn;
|
||||
if (this != &str) {
|
||||
if (_data) delete _data;
|
||||
_len = str._len;
|
||||
_init_data(str._data);
|
||||
} else {
|
||||
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
~MyStringNoMove() { // dtor 默认是noexcept
|
||||
++Dtor;
|
||||
if (_data)
|
||||
delete _data;
|
||||
}
|
||||
|
||||
bool
|
||||
operator<(const MyStringNoMove &rhs) const {
|
||||
return string(this->_data) < string(rhs._data);
|
||||
}
|
||||
|
||||
bool
|
||||
operator==(const MyStringNoMove &rhs) const {
|
||||
return string(this->_data) == string(rhs._data);
|
||||
}
|
||||
|
||||
char *get() const {
|
||||
return _data;
|
||||
}
|
||||
};
|
||||
|
||||
size_t MyStringNoMove::DCtor = 0; // default-ctor
|
||||
size_t MyStringNoMove::Ctor = 0; // ctor
|
||||
size_t MyStringNoMove::CCtor = 0; // copy-ctor
|
||||
size_t MyStringNoMove::CAsgn = 0; // copy-assignment
|
||||
size_t MyStringNoMove::MAsgn = 0; // move-assignment
|
||||
size_t MyStringNoMove::MCtor = 0; // move-ctor
|
||||
size_t MyStringNoMove::Dtor = 0; // dtor
|
||||
// move aware class
|
||||
|
||||
class MyString {
|
||||
public:
|
||||
static size_t DCtor; // default-ctor
|
||||
static size_t Ctor; // ctor
|
||||
static size_t CCtor; // copy-ctor
|
||||
static size_t CAsgn; // copy-assignment
|
||||
static size_t MCtor; // move-ctor
|
||||
static size_t MAsgn; // move-assignment
|
||||
static size_t Dtor; // dtor
|
||||
private:
|
||||
char *_data;
|
||||
size_t _len;
|
||||
|
||||
void _init_data(const char *s) {
|
||||
_data = new char[_len];
|
||||
memcpy(_data, s, _len);
|
||||
_data[_len] = '\0';
|
||||
};
|
||||
public:
|
||||
MyString() : _data(NULL), _len(0) { ++DCtor; }
|
||||
|
||||
MyString(const char *p) : _len(strlen(p)) {
|
||||
++Ctor;
|
||||
_init_data(p);
|
||||
}
|
||||
|
||||
// copy ctor
|
||||
MyString(const MyString &str) {
|
||||
++CCtor;
|
||||
_init_data(str._data);
|
||||
}
|
||||
|
||||
// move ctor
|
||||
MyString(MyString &&str) noexcept: _data(str._data), _len(str._len) {
|
||||
++MCtor;
|
||||
str._len = 0;
|
||||
str._data = NULL; // 重要
|
||||
}
|
||||
|
||||
// copy assignment
|
||||
MyString &operator=(const MyString &str) {
|
||||
++CAsgn;
|
||||
if (this != &str) {
|
||||
if (_data) delete _data;
|
||||
_len = str._len;
|
||||
_init_data(str._data);
|
||||
} else {
|
||||
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// move assignment
|
||||
MyString &operator=(MyString &&str) {
|
||||
++MAsgn;
|
||||
if (this != &str) {
|
||||
if (_data) delete _data;
|
||||
_data = str._data;
|
||||
_len = str._len;
|
||||
str._len = 0;
|
||||
str._data = NULL;
|
||||
} else {
|
||||
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
~MyString() { // dtor 默认是noexcept
|
||||
++Dtor;
|
||||
if (_data)
|
||||
delete _data;
|
||||
}
|
||||
|
||||
bool
|
||||
operator<(const MyString &rhs) const {
|
||||
return string(this->_data) < string(rhs._data);
|
||||
}
|
||||
|
||||
bool
|
||||
operator==(const MyString &rhs) const {
|
||||
return string(this->_data) == string(rhs._data);
|
||||
}
|
||||
|
||||
char *get() const {
|
||||
return _data;
|
||||
}
|
||||
};
|
||||
|
||||
size_t MyString::DCtor = 0; // default-ctor
|
||||
size_t MyString::Ctor = 0; // ctor
|
||||
size_t MyString::CCtor = 0; // copy-ctor
|
||||
size_t MyString::CAsgn = 0; // copy-assignment
|
||||
size_t MyString::MAsgn = 0; // move-assignment
|
||||
size_t MyString::MCtor = 0; // move-ctor
|
||||
size_t MyString::Dtor = 0; // dtor
|
||||
namespace std {
|
||||
template<>
|
||||
struct hash<MyStringNoMove> : public __hash_base<size_t, MyStringNoMove> {
|
||||
size_t
|
||||
operator()(const MyStringNoMove &s) const noexcept {
|
||||
return hash<string>()(string(s.get()));
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct hash<MyString> : public __hash_base<size_t, MyString> {
|
||||
size_t
|
||||
operator()(const MyString &s) const noexcept {
|
||||
return hash<string>()(string(s.get()));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void output_static_data(const T &myStr) {
|
||||
cout << typeid(myStr).name() << "==" << endl;
|
||||
cout << "CCtor=" << T::CCtor
|
||||
<< ",MCtor=" << T::MCtor
|
||||
<< ",CAsgn=" << T::CAsgn
|
||||
<< ",MAsgn=" << T::MAsgn
|
||||
<< ",Dtor=" << T::Dtor
|
||||
<< ",Ctor=" << T::Ctor
|
||||
<< ",DCtor=" << T::DCtor
|
||||
<< endl;
|
||||
}
|
||||
|
||||
|
||||
template<typename M, typename NM>
|
||||
void test_moveable(M c1, NM c2, long &value) {
|
||||
cout << "\n\ntest, with moveable elements" << endl;
|
||||
typedef typename iterator_traits<typename M::iterator>::value_type V1type;
|
||||
clock_t timeStart = clock();
|
||||
for (long i = 0; i < value; i++) {
|
||||
string buf = to_string(i);
|
||||
auto ite = c1.end();
|
||||
c1.insert(ite, V1type(buf.c_str()));
|
||||
}
|
||||
cout << "construction,milli-seconds:" << clock() - timeStart << endl;
|
||||
cout << "size()=" << c1.size() << endl;
|
||||
output_static_data(*(c1.begin()));
|
||||
|
||||
// 容器本身操作
|
||||
timeStart = clock();
|
||||
M c11(c1);
|
||||
cout << "copy, milli-seconds: " << (clock() - timeStart) << endl;
|
||||
timeStart = clock();
|
||||
M c12(move(c1));
|
||||
cout << "move copy, milli-seconds: " << (clock() - timeStart) << endl;
|
||||
timeStart = clock();
|
||||
c11.swap(c12);
|
||||
cout << "swap, milli-seconds: " << (clock() - timeStart) << endl;
|
||||
|
||||
//測試 non-moveable
|
||||
cout << "\n\ntest, with non-moveable elements" << endl;
|
||||
typedef typename iterator_traits<typename NM::iterator>::value_type V2type;
|
||||
timeStart = clock();
|
||||
for (long i = 0; i < value; ++i) {
|
||||
string buf = to_string(i);
|
||||
auto ite = c2.end();
|
||||
c2.insert(ite, V2type(buf.c_str()));
|
||||
}
|
||||
|
||||
cout << "construction, milli-seconds : " << (clock() - timeStart) << endl;
|
||||
cout << "size()= " << c2.size() << endl;
|
||||
output_static_data(*(c2.begin()));
|
||||
|
||||
// 容器本身操作
|
||||
timeStart = clock();
|
||||
NM c21(c2);
|
||||
cout << "copy, milli-seconds : " << (clock() - timeStart) << endl;
|
||||
|
||||
timeStart = clock();
|
||||
NM c22(std::move(c2));
|
||||
cout << "move copy, milli-seconds : " << (clock() - timeStart) << endl;
|
||||
|
||||
timeStart = clock();
|
||||
c21.swap(c22);
|
||||
cout << "swap, milli-seconds: " << (clock() - timeStart) << endl;
|
||||
}
|
||||
|
||||
int main() {
|
||||
long value = 3000; // vector 测试结果的MCtor与CCtor结果大于3000000,是因为vector的动态扩容,当容量不够的时候,会动态分配并进行拷贝。
|
||||
// test_moveable(vector<MyString>(), vector<MyStringNoMove>(), value);
|
||||
// test_moveable(list<MyString>(), list<MyStringNoMove>(), value);
|
||||
// test_moveable(deque<MyString>(), deque<MyStringNoMove>(), value);
|
||||
// test_moveable(multiset<MyString>(), multiset<MyStringNoMove>(), value);
|
||||
// test_moveable(unordered_multiset<MyString>(), unordered_multiset<MyStringNoMove>(), value);
|
||||
return 0;
|
||||
}
|
26
c++2.0/noexcept.cpp
Normal file
26
c++2.0/noexcept.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
//
|
||||
// Created by light on 19-11-3.
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
|
||||
// noexcepte ()中可以加条件
|
||||
// 异常可传递 a调用b b抛出异常,a没处理,就会抛出异常
|
||||
// 1.异常的回传机制:调用foo如果抛出异常,foo会接着往上层抛出异常,
|
||||
// 如果最上层没有处理,则会调用terminate函数,terminate函数内部调用abort,使程序退出
|
||||
|
||||
|
||||
// 2.在使用vector deque等容器的移动构造和移动赋值的时候,如果移动构造和移动赋值没有加上noexcept,
|
||||
// 则容器增长的时候不会调用move constructor,效率就会偏低,所以后面需要加上noexcept,安心使用。
|
||||
|
||||
void foo() noexcept(true) {
|
||||
}
|
||||
|
||||
int main() {
|
||||
foo();
|
||||
vector<int> vec;
|
||||
return 0;
|
||||
}
|
34
c++2.0/nullptr.cpp
Normal file
34
c++2.0/nullptr.cpp
Normal file
@ -0,0 +1,34 @@
|
||||
//
|
||||
// Created by light on 19-11-2.
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
void f(int i) {
|
||||
cout<<"void f(int i)" <<endl;
|
||||
}
|
||||
|
||||
void f(void *p) {
|
||||
cout<<"void f(void *p)" <<endl;
|
||||
}
|
||||
int main() {
|
||||
f(0);
|
||||
|
||||
// #ifndef __cplusplus
|
||||
// #define NULL ((void *)0)
|
||||
// #else /* C++ */
|
||||
// #define NULL 0
|
||||
|
||||
// c语言中将NULL定义为空指针,而在c++中直接定义为0,这是因为C++是强类型的,void *是不能隐式转换成其他指针类型的。
|
||||
|
||||
if(NULL==0) cout<<"NULL==0"<<endl;
|
||||
// f(NULL); // ambiguous,因为NULL==0所以存在二义性 指针也可以是个int的地址
|
||||
// c++11 空指针nullptr
|
||||
f(nullptr); //typedef decltype(nullptr) nullptr_t;
|
||||
// nullptr_t为nullptr的类型
|
||||
nullptr_t nl; // 使用nullptr_t定义的任何变量都具有nullptr一样的行为
|
||||
f(nl);
|
||||
|
||||
return 0;
|
||||
}
|
24
c++2.0/override.cpp
Normal file
24
c++2.0/override.cpp
Normal file
@ -0,0 +1,24 @@
|
||||
//
|
||||
// Created by light on 19-11-3.
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class Base {
|
||||
public:
|
||||
Base(){}
|
||||
virtual void func() {}
|
||||
};
|
||||
class Derivered:public Base{
|
||||
virtual void func(int) override {} //error: ‘virtual void Derivered::func(int)’ marked ‘override’, but does not override
|
||||
};
|
||||
// override用于虚函数,上面的virtual void func(int)实际上不是重写父类的虚函数,而是定义一个新的虚函数,
|
||||
// 我们的本意是重写虚函数,当不加overrride的时候,这样写编译器不会报错,
|
||||
// 那如果像下面加上override的话,则会报错,表示告诉了编译器,我确实要重写,但写错了,没有重写,于是就报错了,
|
||||
// 这样就能给我们对虚函数的重写做检查!
|
||||
|
||||
int main() {
|
||||
|
||||
}
|
91
c++2.0/rvalue.cpp
Normal file
91
c++2.0/rvalue.cpp
Normal file
@ -0,0 +1,91 @@
|
||||
//
|
||||
// Created by light on 19-11-4.
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
#include <complex>
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
|
||||
// Rvalue references 解决非必要的拷贝 当赋值右手边是一个"右值",左手边对象可以偷右手边对象,而不需要重新分配内存。
|
||||
// 浅copy
|
||||
int foo() { return 5; }
|
||||
|
||||
class Foo {
|
||||
public:
|
||||
Foo() = default;
|
||||
|
||||
Foo(const Foo &foo) = default;
|
||||
|
||||
Foo(Foo &&foo) noexcept {}
|
||||
};
|
||||
|
||||
|
||||
// 判断调用哪一个函数
|
||||
void process(int &i) {
|
||||
cout << "左值传入" << endl;
|
||||
}
|
||||
|
||||
void process(int &&i) {
|
||||
cout << "右值传入" << endl;
|
||||
}
|
||||
|
||||
void UnPerfectForward(int &&i) {
|
||||
cout << "forward(int&& i)" << endl;
|
||||
process(i);
|
||||
}
|
||||
// std::forward()实现就是下面这样
|
||||
void PerfectForward(int &&i) {
|
||||
cout << "forward(int&& i)" << endl;
|
||||
process(static_cast<int&&>(i));
|
||||
}
|
||||
// Lvalue: 变量
|
||||
// Rvalue: 临时对象就是个右值,右值不可以放在左边
|
||||
int main() {
|
||||
int a = 9, b = 4;
|
||||
|
||||
a = b;
|
||||
b = a;
|
||||
// a+b=42;// error Rvalue
|
||||
|
||||
string s1("hello");
|
||||
string s2("world");
|
||||
s1 + s2 = s2; // ok
|
||||
string() = "ok"; // ok
|
||||
|
||||
cout << "s2:" << s1 + s2 << endl;
|
||||
cout << "s1:" << s1 << endl;
|
||||
cout << "s2:" << s2 << endl;
|
||||
|
||||
complex<int> c1(3, 8), c2(1, 0);
|
||||
c1 + c2 = complex<int>(3, 4); // ok
|
||||
complex<int>() = complex<int>(1, 2); // ok
|
||||
|
||||
int x = foo();
|
||||
// int *p=&foo(); //error! Rvalue不可以取地址
|
||||
// foo()=7; // error
|
||||
// Rvalue references
|
||||
// vector<Foo> vec;
|
||||
// vec.insert(vec.begin(), Foo()); // Rvalue references and Move Semantics
|
||||
// 原先是下面这个
|
||||
// iterator insert(const_iterator __position, const value_type& __x);
|
||||
// 调用下面这个Move Semantics
|
||||
// iterator insert(const_iterator __position, value_type&& __x) // 然后转交给Foo(Foo&& foo)
|
||||
// { return emplace(__position, std::move(__x)); }
|
||||
// Foo()这个临时对象为右值交给insert的move assignment然后再交给Foo的move ctor。中间有可能会丢失一些信息。
|
||||
|
||||
int aa = 1;
|
||||
process(aa); // L
|
||||
process(1); // R
|
||||
process(move(aa)); // R
|
||||
|
||||
UnPerfectForward(2); // 希望通过转交调用的是右值传入函数,可是调用的是左值传入 这就是个Unperfect Forwarding
|
||||
UnPerfectForward(move(aa)); // 同上
|
||||
// 那如何设计Perfect Forwarding?
|
||||
// 为传递加上static_cast<int &&>强转或者直接使用std::forward()
|
||||
PerfectForward(2);
|
||||
PerfectForward(move(aa));
|
||||
|
||||
return 0;
|
||||
}
|
25
c++2.0/template_template.cpp
Normal file
25
c++2.0/template_template.cpp
Normal file
@ -0,0 +1,25 @@
|
||||
//
|
||||
// Created by light on 19-11-3.
|
||||
//
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
|
||||
using namespace std;
|
||||
// template template parameter 模板模板参数
|
||||
template<typename T,
|
||||
template<typename U> class Container>
|
||||
class XCls {
|
||||
private:
|
||||
Container<T> c;
|
||||
};
|
||||
|
||||
// alias template
|
||||
template<typename T>
|
||||
using Lst = list<T>;
|
||||
|
||||
int main() {
|
||||
// XCls<string, list> mylist1; // error
|
||||
XCls<string, Lst> mylist2;
|
||||
|
||||
return 0;
|
||||
}
|
27
c++2.0/tuple.cpp
Normal file
27
c++2.0/tuple.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
//
|
||||
// Created by light on 19-11-4.
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
#include <tuple>
|
||||
|
||||
using namespace std;
|
||||
|
||||
// tuple使用
|
||||
int main() {
|
||||
tuple<int, int, string> t, t1, t2;
|
||||
t = make_tuple(1, 2, "qwe");
|
||||
t1 = make_tuple(3, 2, "qwe");
|
||||
t2 = make_tuple(3, 2, "qwe");
|
||||
int a = get<0>(t);
|
||||
get<0>(t) = get<1>(t); // 可以修改
|
||||
cout << a << endl;
|
||||
cout << (get<0>(t) > get<1>(t) ? "true" : "false") << endl; // 比较大小
|
||||
cout << (t1 == t2 ? "true" : "false") << endl;
|
||||
typedef tuple<int, int, int, string> T;
|
||||
cout << tuple_size<T>::value << endl; // meta programming 处理类型
|
||||
cout << tuple_size<T>::value << endl;
|
||||
tuple_element<1, T>::type a1 = 10;
|
||||
cout << a1 << endl;
|
||||
return 0;
|
||||
}
|
45
c++2.0/type_alias.cpp
Normal file
45
c++2.0/type_alias.cpp
Normal file
@ -0,0 +1,45 @@
|
||||
//
|
||||
// Created by light on 19-11-3.
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
|
||||
// 第一种使用
|
||||
// type alias
|
||||
// 等价于typedef void(*func)(int, int);
|
||||
using fun=void (*)(int, int);
|
||||
|
||||
void example(int, int) {}
|
||||
|
||||
// 第二种使用
|
||||
template<typename T>
|
||||
struct Container {
|
||||
using value_type=T; // 等价于typedef T value_type;
|
||||
};
|
||||
|
||||
template<typename Cn>
|
||||
void func2(const Cn &cn) {
|
||||
typename Cn::value_type n;
|
||||
}
|
||||
|
||||
// 第三种使用
|
||||
// alias template
|
||||
template<typename CharT>
|
||||
using string=basic_string<CharT, char_traits<CharT>>;
|
||||
// 等价于 typedef basic_string<char> string;
|
||||
|
||||
// 综上:type alias等价于typedef,没有什么不同
|
||||
// using 的所有用法拓展如下:
|
||||
// 1.using-directives
|
||||
// using namespace std; or using std::cout;
|
||||
// 2. using-declaration
|
||||
// protected:
|
||||
// using _Base::_M_alloc;
|
||||
// 3.c++2.0特性 type alias and alias template
|
||||
int main() {
|
||||
fun fn = example; // 函数指针
|
||||
return 0;
|
||||
}
|
14
c++2.0/uniform_initialization.cpp
Normal file
14
c++2.0/uniform_initialization.cpp
Normal file
@ -0,0 +1,14 @@
|
||||
//
|
||||
// Created by light on 19-11-2.
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main() {
|
||||
int value[]{1, 2, 3}; // initializer_list<T> 会关联一个array<T,n> 里面元素被编译器逐一分解传给函数
|
||||
vector<int> v{2, 3, 5};
|
||||
return 0;
|
||||
}
|
66
c++2.0/variadic/variadic.cpp
Normal file
66
c++2.0/variadic/variadic.cpp
Normal file
@ -0,0 +1,66 @@
|
||||
//
|
||||
// Created by light on 19-11-2.
|
||||
//
|
||||
|
||||
// variadic template(c++11) 数量不定的模板参数
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <tuple>
|
||||
|
||||
using namespace std;
|
||||
// 参数个数 参数个数逐一递减
|
||||
// 参数类型 参数类型也逐一递减
|
||||
|
||||
// (3)
|
||||
// 需要重载一个终止函数
|
||||
template<typename T>
|
||||
void _hash(size_t &seed, const T &val) {
|
||||
cout << "hash over " << val << endl;
|
||||
}
|
||||
|
||||
// (2)
|
||||
// 展开函数, 把参数分为一个普通参数和一个参数包,调用一次,参数包大小就减一
|
||||
template<typename T,typename... Args>
|
||||
void _hash(size_t &seed, const T& val,const Args &... args) {
|
||||
cout << "parameter " << val<< endl;
|
||||
// 递归调用自己
|
||||
_hash(seed, args...); // 上面如果不给T参数,会自己调用自己成死循环
|
||||
}
|
||||
|
||||
|
||||
// 泛化版 (1)
|
||||
template<typename ...Args>
|
||||
size_t _hash(const Args &... args) {
|
||||
cout << "hash start " << endl;
|
||||
size_t seed = 10;
|
||||
// 递归调用自己
|
||||
_hash(seed, args...);
|
||||
return seed;
|
||||
}
|
||||
|
||||
|
||||
template<typename ...Args>
|
||||
class A {
|
||||
private:
|
||||
int size = 0; // c++11 支持类内初始化
|
||||
public:
|
||||
A() {
|
||||
size = sizeof...(Args);
|
||||
cout << size << endl;
|
||||
}
|
||||
};
|
||||
|
||||
int main(void) {
|
||||
size_t f = 10;
|
||||
_hash("asdas", 2, 3, 4);
|
||||
A<int, string, vector<int>> a; // 类型任意
|
||||
|
||||
// Tuple就是利用这个特性(变长参数模板)
|
||||
tuple<int, string> t = make_tuple(1, "hha");
|
||||
int firstArg = get<0>(t);
|
||||
string secondArg = get<1>(t);
|
||||
cout << firstArg << " " << secondArg << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
32
c++2.0/variadic/variadic1.cpp
Normal file
32
c++2.0/variadic/variadic1.cpp
Normal file
@ -0,0 +1,32 @@
|
||||
//
|
||||
// Created by light on 19-11-4.
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
#include <bitset>
|
||||
|
||||
using namespace std;
|
||||
|
||||
// example 1
|
||||
void printX() {
|
||||
|
||||
}
|
||||
|
||||
// 特化
|
||||
template<typename T, typename... Type>
|
||||
void printX(const T &firstArg, const Type &...args) {
|
||||
cout << firstArg << endl; // 先减少一个做操作
|
||||
printX(args...); // 其余的继续分为一个+一包进行递归知道没有了 调用printX()
|
||||
}
|
||||
|
||||
// 如果写了下面接收任意参数,下面这个跟上面可以共存 泛化版 永远不会被调用,前面特化把它取代了
|
||||
template<typename T, typename... Type>
|
||||
void printX(const Type &...args) {
|
||||
printX(args...);
|
||||
}
|
||||
|
||||
|
||||
int main() {
|
||||
printX(1, "hello", bitset<16>(377), 42);
|
||||
return 0;
|
||||
}
|
34
c++2.0/variadic/variadic2.cpp
Normal file
34
c++2.0/variadic/variadic2.cpp
Normal file
@ -0,0 +1,34 @@
|
||||
//
|
||||
// Created by light on 19-11-4.
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
void print(const char *s) {
|
||||
while (*s) {
|
||||
if (*s == '%' && *(++s) != '%')
|
||||
throw std::runtime_error("invalid format string: missing arguments");
|
||||
std::cout << *s++;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, typename... Args>
|
||||
void print(const char *s, T value, Args... args) {
|
||||
while (*s) {
|
||||
if (*s == '%' && *(++s) != '%') {
|
||||
std::cout << value;
|
||||
print(++s, args...); // 即便当 *s == 0 也会产生调用,以检测更多的类型参数。
|
||||
return;
|
||||
}
|
||||
std::cout << *s++;
|
||||
}
|
||||
throw std::logic_error("extra arguments provided to printf");
|
||||
}
|
||||
|
||||
int main() {
|
||||
int *pi = new int;
|
||||
print("%d %s %p %f\n", 15, "Acc", pi, 3.14);
|
||||
return 0;
|
||||
}
|
31
c++2.0/variadic/variadic3_4.cpp
Normal file
31
c++2.0/variadic/variadic3_4.cpp
Normal file
@ -0,0 +1,31 @@
|
||||
//
|
||||
// Created by light on 19-11-4.
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
// 参数type相同的max
|
||||
int max(initializer_list<int> initializerList) {
|
||||
int res = *initializerList.begin();
|
||||
for (auto elem:initializerList)
|
||||
res = max(res, elem);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
// 参数type相同的maximum
|
||||
int maximum(int n) {
|
||||
return n;
|
||||
}
|
||||
|
||||
template<typename ...Args>
|
||||
int maximum(int n, Args...args) {
|
||||
return std::max(n, maximum(args...));
|
||||
}
|
||||
|
||||
int main() {
|
||||
cout << max({10, 8, 100, 1}) << endl;
|
||||
cout << maximum(57, 48, 60, 100, 20, 18) << endl;
|
||||
}
|
44
c++2.0/variadic/variadic5.cpp
Normal file
44
c++2.0/variadic/variadic5.cpp
Normal file
@ -0,0 +1,44 @@
|
||||
//
|
||||
// Created by light on 19-11-4.
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
#include <tuple>
|
||||
#include <bitset>
|
||||
|
||||
using namespace std;
|
||||
|
||||
// tuple递归调用
|
||||
|
||||
// 得出这种打印[7,5....,42]
|
||||
// 需要知道有几个以及现在操作的是第几个 sizeof...()
|
||||
|
||||
// cout<< make_tuple(7.5,string("hello"),bitset<16>(377),47);
|
||||
|
||||
|
||||
template<int IDX, int MAX, typename... Args>
|
||||
struct print_tuple {
|
||||
static void print(ostream &os, const tuple<Args...> &t) {
|
||||
os << get<IDX>(t) << (IDX + 1 == MAX ? "" : ",");
|
||||
print_tuple<IDX + 1, MAX, Args...>::print(os, t);
|
||||
}
|
||||
};
|
||||
|
||||
// 偏特化
|
||||
template<int MAX, typename... Args>
|
||||
struct print_tuple<MAX, MAX, Args...> {
|
||||
static void print(ostream &os, const tuple<Args...> &t) {
|
||||
}
|
||||
};
|
||||
|
||||
template<typename ... Args>
|
||||
ostream &operator<<(ostream &os, const tuple<Args...> &t) {
|
||||
os << "[";
|
||||
print_tuple<0, sizeof...(Args), Args...>::print(os, t);
|
||||
return os << "]";
|
||||
}
|
||||
|
||||
|
||||
int main() {
|
||||
cout << make_tuple(7.5, string("hello"), bitset<16>(377), 47) << endl;
|
||||
}
|
52
c++2.0/variadic/variadic6.cpp
Normal file
52
c++2.0/variadic/variadic6.cpp
Normal file
@ -0,0 +1,52 @@
|
||||
//
|
||||
// Created by light on 19-11-4.
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
|
||||
|
||||
using namespace std;
|
||||
// 上一个例子:variadic5.cpp为递归调用
|
||||
// 当前这个例子为递归继承
|
||||
namespace light {
|
||||
template<typename...Values>
|
||||
class tuple;
|
||||
|
||||
template<>
|
||||
class tuple<> {
|
||||
};
|
||||
|
||||
template<typename Head, typename...Tail>
|
||||
class tuple<Head, Tail...> : private tuple<Tail...> {
|
||||
typedef tuple<Tail...> inherited;
|
||||
protected:
|
||||
Head m_head;
|
||||
public:
|
||||
tuple() {}
|
||||
|
||||
tuple(Head h, Tail...tail) : m_head(h), inherited(tail...) {}
|
||||
|
||||
// decltype()中的m_head必须放到前面,否则编译器找不到
|
||||
auto head() -> decltype(m_head) { return m_head; }
|
||||
// 或者 Head head() { return m_head; }
|
||||
|
||||
inherited &tail() { return *this; }
|
||||
};
|
||||
}
|
||||
/**
|
||||
* string 32 8字节对齐
|
||||
* float 4
|
||||
* int 4
|
||||
* 4+4+32=40 自底向上
|
||||
*/
|
||||
|
||||
int main() {
|
||||
using light::tuple;
|
||||
tuple<int, float, string> t(41, 6.3, "nico");
|
||||
cout << sizeof(t) << endl;
|
||||
cout << t.head() << endl;
|
||||
cout << t.tail().head() << endl;
|
||||
cout << t.tail().tail().head() << endl;
|
||||
|
||||
return 0;
|
||||
}
|
57
c++2.0/variadic/variadic7.cpp
Normal file
57
c++2.0/variadic/variadic7.cpp
Normal file
@ -0,0 +1,57 @@
|
||||
//
|
||||
// Created by light on 19-11-4.
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace light {
|
||||
template<typename...Values>
|
||||
class tuple;
|
||||
|
||||
template<>
|
||||
class tuple<> {
|
||||
};
|
||||
|
||||
template<typename Head, typename...Tail>
|
||||
class tuple<Head, Tail...> {
|
||||
typedef tuple<Tail...> composited;
|
||||
protected:
|
||||
Head m_head;
|
||||
composited m_tai;
|
||||
public:
|
||||
tuple() {}
|
||||
int get() { return sizeof(composited);}
|
||||
tuple(Head h, Tail...tail) : m_head(h), m_tai(tail...) {}
|
||||
|
||||
// decltype()中的m_head必须放到前面,否则编译器找不到
|
||||
auto head() -> decltype(m_head) { return m_head; }
|
||||
// 或者 Head head() { return m_head; }
|
||||
|
||||
composited &tail() { return m_tai; }
|
||||
};
|
||||
}
|
||||
|
||||
// 根据string为8字节对齐,我们得出8字节对齐
|
||||
// 第一次 int 4字节Head调整到边界8 那composite呢?继续往下分析
|
||||
// 第二次 把第一次的composited拆分为float与一包, float也占4字节,调整到8边界为8字节,那这一步的composited呢?继续往下分析
|
||||
// 第三次 把第二次的compoisted拆分成sting与一包, string占32字节,已经为8倍数,无需调整,而这一步的composited呢?由于到这里一包已经没了,就会调用它的全特化版本,全特环版本为空,sizeof为1,
|
||||
// 调整到8的倍数为8.
|
||||
// 因此最后的内存结构(自底向上)为:8 + 8 + 32 + 8 = 56 64位机器结果
|
||||
|
||||
struct A {
|
||||
string a;
|
||||
float b;
|
||||
};
|
||||
int main() {
|
||||
using light::tuple;
|
||||
tuple<int, float, string> t(41, 6.3, "nico");
|
||||
cout<<sizeof(A)<<endl;
|
||||
cout<<t.get()<<endl;
|
||||
cout << sizeof(t) << endl;
|
||||
cout << t.head() << endl;
|
||||
cout << t.tail().head() << endl;
|
||||
cout << t.tail().tail().head() << endl;
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user