现代c++笔记(3)
2021-06-20 本文已影响0人
Teech
- Alias Template
template <typename T>
using Vec = std::vector<T, MyAlloc<T>>
Vec<int> coll;
//define也无法达到相同的效果
//typedef 不能接受参数
//不能对偏特化或者全特化起作用
//打算实现这样
//想萃取test_move(vector<MyString>())中的MyString
typdef typename iterator_traits<typename Container::iterator>::value_type ValType;
- temlate temlate parrameter
//template<typename T, template<typename U> class Container> //写法1
template<typename T, template<class> class Container> //写法2
class XCls {
private:
Container<T> c;
public:
// ...
};
- type alias
//第一种用法
//typedef void (*fun)(); //传统写法
using func = void(*)(); //新标准写法
void example(){}
fun f = example;
//第二种用法
template<typename T>
struct MyContiner
{
using mytype = T;//typedef T mytype
};
//第三种用法 alias tmplelate
template<typename charT>
using myString = std::basic_string<charT, std::char_traits<charT>>;
myString<char> str;
//传统写法typedef不能用于模版
typedef std::basic_string<char, std::char_traits<char>> myString2;
myString2 str2;
- using 作用
//导入命名空间
using namespace std;
using std::cout;
//在class种使用using
protected:
using _Basic::_M_alloc;
//type-alias 以及alias template(c++ 11以后)
- noexcept
//异常如果一直没处理,会一直往调用链往上传递,如果都没处理,最终程序会执行std::abort() 终止程序
//定义一个函数 保证不抛出异常
void foo() noexcept;//void foo() noexcept(true);
//定义一个函数不抛出异常,条件是x.swap(y)不抛出异常
void swap(Type& x,Type& y) noexcept(noexcept(x.swap(y))
{
x.swap(y);
}
//你需要通知c++(特别是vector),你的移动构造以及赋值构造不会抛出异常也就是noexcept,Then,move构造函数才会被调用当vector扩容时,如果没有申明noecept,那么std::vector不能使用它
//https://stackoverflow.com/questions/8001823/how-to-enforce-move-semantics-when-a-vector-grows
class MyString {
private:
char* _data;
size_t len;
public:
//move constructor
MyString(MyString&&str) noexcept
:_data(str._data),len(str.len){
}
MyString& operator=(MyString&& str) noexcept
{
_data = str._data;
len = str.len;
str._data = nullptr;
return *this;
}
};
//std::vector<MyString>不停push_back当发生扩容的时候,到底使用拷贝构造函数还是移动构造函数看MyString种移动构造函数到底有没有申明noexcept
//正常情况下,移动构造以及移动赋值都要申明成noexcept,这样不论使用的容器时申明都会比较安心
- Override
class base {
virtual void fun(float a){}
};
class derived :base {
//这么写会导致新的函数申明
//virtual void fun(int a) {}
//override帮助编译器,如果函数原型不一致会导致编译出错
virtual void fun(int a) override {}
};
- Final
//修饰class表示不能被继承,我是最后一个
class base1 final {
};
class derived :base1 {}
};
//修饰虚函数表示不能被override 否则编译出错
class base2 {
virtual void fun() final {}
};
class devived :base2
{
virtual void fun() {}
};
- Decltype
std::map<int, float> coll;
decltype(coll)::value_type elem;//11之前只能std::map<int, float>::value_type elem
//1.申明返回类型,c++11之前
//打算这么写 但是编译不过 x + y在之前出现
template<typename T1,typename T2>
decltype(x + y) add(T1 x,T2 y);
//所以这么写
//很像lambda
template<typename T1,typename T2>
auto add(T1 x,T2 y) ->decltype(x + y);//auto + -> 指明返回类型
//2.metaprograming 模板
template <typename T>
void test(T obj){
typedef typename decltype(obj)::iterator iType;
//typedef typename T::iterator iType;
}
//3.获取lambda的类型
auto cmp = [](const P& p1,const P& p2){
return p1.lastname() < p2.lastname();
}
std::set<P,decltype(cmp)> col(cmp);
- lambda
lambda是个inline 函数或者可以理解临时对象
auto l = [] {
std::cout << 11;
};
l();
//完整形式
[...](...) mutable(opt) throwSpec(opt) -> retType(opt){...}
[...]:导入器
(...):参数
retType:返回类型
{...}:函数本体
//例子:
int x = 0;
int y = 1;
auto q = [x,&y]{...};//&修饰为传递引用的方式 x为传值的方式
auto q = [=,&y]{...};//=号表示其他外部区域以传值的方式传递
//例子:
int id = 0;
//如果不加mutable ++id不能编译通过 如果传递引用的方式过来就可以
auto f = [id]()mutable {
std::cout << id << std::endl;
++id;
};
id = 42;
f();
f();
std::cout << id << std::endl;
//主要id是传值的方式传递过去的
>out: 0 1 42
lambda相当于匿名的函数对象
class Functor {
private:
int id;
public:
void operator()() {
std::cout << id << std::endl;
}
};