栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

c++11 总结-1

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

c++11 总结-1

文章目录
  • 1、让程序更简洁
    • 1.1、类型推导
    • 1.2、模板细节的改进
    • 1.3、列表初始化
    • 1.4 基于范围的for 循环
    • 1.5 std::funtion 和 bind
    • 1.6 lambda 表达式
    • tuple
  • 2、改进性能
    • 2.1 右值引用
    • move & forward
    • 2.4 emplace_back 减少内存拷贝和移
    • 2.5 无序容器
  • 3、消除重复,提高代码质量
    • 3.1 type_traits 类型萃取
    • 3.2 可变模板参数
      • 函数模板展开
      • 类可变模板展开
      • 其他
    • 3.3 可变模板参数和type_taits 的综合应用
      • 1、optional 的实现
      • lazy 延迟调用
      • dll 帮助类
      • lambda 链式调用
      • any类的实现
      • function_traits
      • variant 的实现
      • ScopeGuard
      • tuple_helper

1、让程序更简洁 1.1、类型推导

1、auto
2、decltype,后置语法(解决前置,参数尚未定义)

1.2、模板细节的改进

1、模板的别名,typedef 改成使用using

2、默认模板参数

template

1.3、列表初始化

1、初始化列表的限制

1、私有或者保护的 非静态的数据成员
2、无基类
3、无虚函数
4、不能有{} 和 =

2、std::initilizer_list 的细节

3个接口 begin, size, end
高效:只是数据的引用
1.4 基于范围的for 循环

for_each 是算法
vector 迭代器是地址指针,如果中间添加数据,导致容量上限,重新申请内存,会到迭代器失效

1.5 std::funtion 和 bind

1、可调用对象

2、bind 可以绑定对应

    auto f = std::bind(std::logical_and(),
    std::bind(std::greater(),std::placeholders::_2,5),
    std::bind(std::less_equal(),
    std::placeholders::_1,std::placeholders::_3));
1.6 lambda 表达式

优点

1、声明式编程风格,更直接,可读性和可维护性更高
2、简洁,开发高效

修改[=] 对应的变量,可以使用mutable
默认是const
1、没有捕获的可以转换成函数指针
2、有捕获的不可以

tuple
元组提供灵活的小结构体,tuple 的解析需要模板元的技巧
2、改进性能 2.1 右值引用

通过避免额外的拷贝来提高效率


常量+左值引用,是万能引用 这也是拷贝构造函数的写法
假设没有移动构造的情况下,Foo(const Foo &) 既可以接收左值,又可以接收右值

move & forward

1、引用折叠

 
    

2、使用static_cast 进行强制转换成右值,move 就是将左值转换成右值

2.4 emplace_back 减少内存拷贝和移
 * emplace_back 
 *  1、减少内存拷贝, 注意vector扩容的问题
 *  2、emplace_back只会构造1次,而push_back 会进行构造并且进行拷贝
 *  3、内部实现是 palcement new ,在指定的内存上进行构造
2.5 无序容器

unordered_map, unordered_set

3、消除重复,提高代码质量

总结:

c ++ 11 进一步增强了c++泛型编程的的能力,尤其是type_traits, 可变参数模板和tuple ,可以在编译期计算,消除重复定义,是程序更为简洁高效

1、实现了在编译期进行计算、查询、判断、转换,增加泛型编程的能力,很好的支持模板元编程

2、例如:可变模板参数,可以支持更多的函数,避免大量重复代码重载。

3、判断

  • optional 的实现
  • lazy 延迟调用
  • dll 帮助类
  • lambda 链式调用
  • any类的实现
  • function_traits
  • variant 的实现
  • ScopeGuard
  • tuple_helper

名词:

圈复杂度(Cyclomatic complexity)是一种代码复杂度的衡量标准

3.1 type_traits 类型萃取
 

1、decay 可以去掉cv 和引用

// 使用去掉引用 和 cv 太长了
template 
typename std::remove_cv::type>::type* getA() {
    using V = typename std::remove_cv::type>::type;
    return new V();
}

// 使用decay 衰退, 更加简洁
template 
typename std::decay * getV() {
     using V = std::decay;
    return new V();
}

2、conditional , 选择类型

std::conditional::type; 

3、 resulte_of, decltype, 3种返回类型

//返回值
template 
decltype((*(F*)0)(*(Args*)0)) func1(F f, Args a) {
    return f(a);
}
template 
auto func1(F f, Args a) -> decltype(f(a)){
    return f(a);
}

template 
typename std::result_of::type func1(F f, Args a) {
    return f(a);
}

4、enable_if 可以用于函数重载,如果是false 函数类型不支持

template ::type>
void func_enable_if(){

}

template ::type>
void func_enable_if2(){

}

5、is_same, is_base_of, is_convertible

class A{};
class B :public A {

};
void test_is_between_type() {
    std::cout << std::is_same::value << std::endl;
    std::cout << std::is_base_of::value << std::endl;
    std::cout << std::is_convertible::value << std::endl;
}

3.2 可变模板参数
 
函数模板展开 

1、函数模板展开(递归方式)

void print() {

}
template
void print(T t, Args ...args) {
    cout << t << endl;
    print(args...);
}

2、函数模板展开(逗号+初始化列表)

template 
void print(U u) {
    cout << u << endl;
}
template 
void func1(Args ...arg) {
    int arr[] = {(print(arg),0)...}; //逗号+初始化列表
    initializer_list a{(print(arg),0)...}; //
    
    //gcc 还不支持
    //initializer_list b{([&]{print(arg);}(),0)...}; //lambda

}

3、函数模板展开(enable_if常量参数, 递归中一种)

template
typename enable_if::value>::type printTp() {
    
}

template
typename enable_if::value>::type printTp() {
    printTp();
}
类可变模板展开

1、通过特化展开

// 第一部分,前项声明,这是可变参数模板类
template  
class Sum {

};

// 第二部分,如何展开的部分
template  
class Sum { //类上添加<> 表示特化
    enum { value = Sum::value + Sum::value};
};

// 第三部分,特化的终止类
template  
class Sum {
    enum{ value = sizeof(Last)};
};

2、继承展开

// 第一部分前置声明
template
class IndexSeq{};

// 第二部分
template
struct MakeIndex : MakeIndex {
};

// 第三部分,终止类
template 
struct MakeIndex<0, Indexes...> { //在N 等于 0的时候终止
    typedef IndexSeq type; //在基类中基类
};

void test_class_variable_template() {
    using T = MakeIndex<3>::type;
    cout << typeid(T).name() << endl;

}

//展开tuple

// 使用 Index 和 tuple 打印模板参数
template
void helper_tuple(IndexSeq index,tuple tup) {
    print(get(tup)...);
}

template  
void printArgs(Args ... args) {
    //sizeof...(args) 可以获取参数个数
    helper_tuple(typename MakeIndex::type(),make_tuple(args...));
}
其他
template 
T * instance(Args ... args) {

    //存在拷贝问题, 存在性能消耗
    //return new T(args...);

    // forward
    return new T(forward(args)...);

}
3.3 可变模板参数和type_taits 的综合应用 1、optional 的实现
1、内存对齐和 placement new, 申请内存aligned_storage
2、类型转换  operator bool()
3、void operator() (int a) ,解决数据依赖,由对象存储数据


struct A {
    int t;
};

template 
class Optional {
public:
    template 
    T* getInstance(Args... args) {
        return new(&m_data) T(args...);
    }

    ~Optional() {
        ((T*)(&m_data))->~T();
    }

    // 类型转换
    operator bool() {
        // 
        return false;
    }

    //运算符重载
    T& operator *() {
        return *((T*)(&m_data));
    }

    // 仿函数
    void operator() (int a) {

    }

private:
    using data_t = std::aligned_storage::value>;
    data_t m_data;
};

void test_operator() {
    Optional a;

    if(a) { //判断是否初始化,根据类型强转 ,operator bool()
        *a; // 调用 T& operator *()
        a(1);
    }
}
lazy 延迟调用

1、利用 lambda 将参数, 或者bind

m_func = [&f, &args...] {return f(args...);}

m_func = std::bind(&f, std::forward(args)...);
dll 帮助类

解决的问题

1、每个调用dll 获取参数,需要声明方法,比较繁琐
2、利用 模板减少对函数的声明
3、利用 可变参数模板,可以完成函数带参数的调用

template 
std::function GetFuntion(const std::string & name ) {
    auto funcAddresss = GetProcAddress(m_hmod, name.c_str());
    return std::function((T*)funcAddress);
}

template  
typename std::result_of(Args...)>::type ExecFunction(const std::string &name, Args... args) {
    return GetFuntion(name)(std::forward(args)...);
}

lambda 链式调用

1、使用lambda 延迟调用

2、每次调用 then 返回task 对象,新对象先执行之前的task 的func, 然后调用自己f

3、调用过程 task.then({调用1}).then({调用2}).run(1); 调用1先执行 ,在执行调用2, run 的参数是调用1的

可以简单压栈过程,调用1被第一个压栈,但是调用是dfs递归调用,这样调用1就被优先调用

template 
class TaskA;
template  
class TaskA {
public:
    TaskA(std::function &&f) : m_fun(f){}
    TaskA(std::function &f) : m_fun(f){}

    R run(Args&&...args) {
        return m_fun(std::forward(args)...);
    }

    template
    auto then(F && f) -> TaskA::type(Args...)>{
        // 获取F的返回值
        using NewType = typename std::result_of::type(Args...);

        // 新创建一个task 对象,先执行之前的task 的func, 然后调用自己f
        auto newFun = [&f,this](Args&&...args){
            auto ret = m_fun(std::forward(args)...);
            return f(ret);
        };

        return TaskA(newFun);
    }

    std::function m_fun;
};

void test_lambda_task() {
    //调用过程 task.then({调用1}).then({调用2}).run(1);
    // 套娃,没添加一个then 就套一层。执行过程是,先执行m_fun, 然后在执行fun;
    Task task{[](int a,int b) {
        std::cout << 1 << std::endl;
        return a + 1;
    }};

    auto task1  = task.then([](int a)->double {
            std::cout << 2 << std::endl;
            return a + 2;
        });
    auto task2 = task1.then([](double a) {
        std::cout << 3 << std::endl;
            return a + 2;
    });

    task2.run(1,2);
}
any类的实现

1、类型存储,使用base 进程存储,子类中存储value

2、通过typeid 获取类型的type_index,存储到any 中,在cast 时候先判断type_index 是否相同

3、如果相同,将base 转换 dynamic_cast

class Any {
public:
    Any(): m_typeInfo(typeid(void)){}

    //通过构造 模板,
    // 限制不能是Any 类作为参数,因为是拷贝构造应该处理的
    template ::type, Any>::value, U>::type>
    Any(U&& u)
            : m_typeInfo(type_index(typeid(typename decay::type))),
              m_base(new Derived::type>(u)) {
    }

    //更加tpyeinfo 来确定是否相同
    template
    bool is() {
        return type_index(typeid(typename decay::type)) == m_typeInfo;
    }


    template
    U& AnyCast() {
        if(!is()) {
            throw bad_cast();
        }

        auto d = dynamic_cast*>(m_base.get());
        if (d) {
            return d->value;
        } else {
            throw bad_cast();
        }
    }


private:
    struct base {
        virtual ~base(){}

    };

    template
    struct Derived : public base
    {
        //构造
        Derived(T && t) : value(std::forward(t)){}
        Derived(T & t) : value(t){}

        T value;
    };
    
    unique_ptr m_base;
    type_index m_typeInfo;
};

void test_any() {
    Any a(1);
    int b = a.AnyCast();
}

function_traits

#include 
#include 
#include  //类型萃取
#include 
#include  //typeid
#include    //ptr

using namespace std;

template 
class function_traits;

//通过特化获取返回值
// 基本特化版本
template
struct function_traits{
    enum { arity = sizeof...(Args) };
	using return_type = ReturnType;
	using function_type = ReturnType(Args...);
	using stl_function_type = std::function;
	using pointer = ReturnType(*)(Args...);

	template
	struct args
	{
		static_assert(I < arity, "index is out of range, index must less than sizeof Args");
		using type = typename std::tuple_element>::type;
	};

	using tuple_type = std::tuple>...>;
	using bare_tuple_type = std::tuple>...>;
    
};

//函数指针
template
struct function_traits : function_traits {};

//function
template
struct function_traits> : function_traits {};

// 成员函数
#define FUNCTION_TRAITS(...)
template 
struct function_traits : function_traits{};

FUNCTION_TRAITS()
FUNCTION_TRAITS(const)
FUNCTION_TRAITS(volatile)
FUNCTION_TRAITS(const volatile)

// 函数对象
template
struct function_traits : function_traits {};

//强转成 std::function
template
typename function_traits::stl_function_type to_function(const Function& lambda)
{
	return static_cast::stl_function_type>(lambda);
}
//强转成 std::function
template
typename function_traits::stl_function_type to_function(Function&& lambda)
{
	return static_cast::stl_function_type>(std::forward(lambda));
}
//强转成 函数指针
template
typename function_traits::pointer to_function_pointer(const Function& lambda)
{
	return static_cast::pointer>(lambda);
}

void func(int a,int b) {

}
template
void printType()
{
    cout << typeid(T).name() << endl;
};


float(*cast_func)(int, int, int, int);
float free_function(const string& a, int b)
{
    return (float)a.size() / b;
}
struct AA
{
    int f(int a, int b)volatile { return a + b; }
    int operator()(int)const { return 0; }
};
void test_function_traits()
{
    cout << "----------- 2 ----------" << endl;
    //lambda 
    auto f = [](int a) {return a; };

    //函数
    printType::function_type>();
    //function
    printType>::function_type>();

    //函数
    printType::function_type>();

    //函数指针
    printType::function_type>();
   
    //可调用对象
    printType::function_type>();

    //成员函数
    using T = decltype(&AA::f);
    printType();
    printType::function_type>();

    static_assert(std::is_same::return_type, int>::value, "");
}
variant 的实现

支持制定多种类型的复用,很类似union 的用法,内存也是最大类型的大小,并行内存对齐

制定几种类型,可以存放制定类型的数据

1、取类型size的最大值,递归 conditional 2、检查类型 递归,conditional ,利用is_same 判断
3、std::alignment_of 对齐内存,然后根据MaxSize 来获取大小
4、记录下来当前的type_index, 通过type_id 来获取


template 
struct MaxSize : integral_constant::value ? MaxSize::value : sizeof(T)> {
    using maxType = typename std::conditional::value, typename MaxSize::maxType, T>;
};

template 
struct MaxSize : integral_constant {
    using maxType = T;
};


template 
struct CheckType;

template 
struct CheckType
        : std::conditional::value, std::true_type, typename CheckType::type> {};

template 
struct CheckType : std::false_type {};


template 
struct Variant {
    //只能是在类型中才可以构造
    template ::type, T, Args...>::type::value,
                                                       U>::type>
    Variant(U&& u) :m_typeIndex(typeid(typename std::decay::type)) {
        new(&m_data) (typename std::decay::type)(u);
    }

    template
    bool is() {
        return type_index(typeid(U)) == m_typeIndex;
    }
    template
    U Get() {
        if(!is()) {
            throw bad_cast();
        }

        return (*(U*)&m_data);
    }

    // 内存数据m_data;
    using data_t = std::aligned_storage::value, std::alignment_of::type>::value>;
    data_t  m_data;
    type_index m_typeIndex;
};

int main() {
    Variant a = 1;
    int b = a.Get();
    system("pause");
}
ScopeGuard

利用RAII 机制,在构造时候获取资源,在析构的时候释放资源

1、一般存储的是 function , 等到析构的时候释放

2、lock_guard 就是存储 lock

在考虑下
默认构造、拷贝构造、赋值运算的意义,没有意义就去掉

tuple_helper
  • 递归方式遍历打印
  • 通过索引序列打印
  • 根据类型获取索引值
  • 运行期根据索引获取

模板很重要的是提取类型,例如:tuple,用下面的的方式就可以提前Args… 类型

#include 
#include 
#include 

using namespace std;

template 
struct TupleHelper {
    static void print(const Tuple &t) {
        TupleHelper::print(t);
        cout << std::get(t) << endl;
    }
};

template 
struct TupleHelper {
    static void print(const Tuple &t) {
        cout << std::get<0>(t) << endl;
    }
};


void test_print() {
    tuple t = make_tuple(1,"a",1);
    TupleHelper::value>::print(t);
}



template 
class Index {

};

template 
struct MakeIndex : MakeIndex {

};

template
struct MakeIndex<0,Args...> {
    using type = Index;
};

//把索引分开
template 
void print(U u) {
    cout << u << endl;
}

template  
void printIndexTuple(Index&& index,const Tuple &t) {
    int arr[] = {(print(get(t)),0)...};
}
template
void index_tuple_print(const tuple &s) {
    printIndexTuple(typename MakeIndex::type(),s);
}

void test_index_tuple_print() {
     tuple t = make_tuple(1,"2",3);
     index_tuple_print(t);
}


template 
struct GetIndex;


template 
struct GetIndex : conditional::value,integral_constant ,GetIndex>::type{

};

template 
struct GetIndex : integral_constant{
};

// 模板很重要的是提取类型,例如:tuple,用下面的的方式就可以提前Args... 类型
template
void get_index_tuple(const tuple &s) {
    cout <<"type" << typeid(T).name() <<" index of" << GetIndex<0,T,Args...>() << endl; 
}

void test_get_index() {
    tuple t = make_tuple(1,"2",3);
    get_index_tuple(t);
}


template
typename enable_if::value>::type 
GetArgIndex(int index, const Tuple &t) {

}

template
typename enable_if::value>::type 
GetArgIndex(int index, const Tuple &t) {
    if(index == K) {
        cout << get(t) << endl;
    } else {
        GetArgIndex(index,t);
    }
}

void test_run_index() {
    tuple t = make_tuple(1,"2",3);
    int a = 1;
    GetArgIndex<0>(a,t);
}


template
auto reverseTupleImp(const Tuple& t, Index index) -> decltype(make_tuple(get(t)...)) {
    return make_tuple(get(t)...);
}

template
auto reverseTuple(const tuple &t) -> decltype(reverseTupleImp(move(t),typename MakeIndex::type())) {
    return reverseTupleImp(t,typename MakeIndex::type());
}
void test_reverse_tuple() {
     tuple t = make_tuple(1,"2",3);
     auto rt = reverseTuple(t);
}
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号