zoukankan      html  css  js  c++  java
  • C++11新特性之字节对齐、多参数模版、placement new

    1. 内存对齐

    #pragma pack(push, 1)
    struct A
    {
        char a;
        int b;
        double c;
        char d[11];
    };
    #pragma pack(pop)
    
    #pragma pack(push, 2)
    struct B
    {
        char a;
        int b;
        double c;
        char d[11];
    };
    #pragma pack(pop)
    
    void main()
    {
        cout << sizeof(A) << endl;
        cout << sizeof(B) << endl;
    }

      上面的代码演示了采用#pragma pack()方法实现内存对其。接下来介绍C++11中相关内存对其的方法。

    1.1 alignas

      alignas指定内存对其大小,有时候我们希望不按照默认的内存对齐方式来对齐,这时我们可以用alignas来指定内存对齐。

      在C++11中,只要是一个编译期数值(#define, static const, template)都支持alignas,另外需要注意alignas只能改大不能改小,如果要改小可以使用上面提到的#pragma pack(1)

    1.2 alignof和std::alignment_of

      alignof用来获取内存对齐大小,用法比较简单:

      A a;
      cout << alignof(a) << endl;

      alignof只能返回一个size_t,而std::alignment_of继承自std::integral_constant,拥有value_type,type,value成员

      cout << std::alignment_of<A>::value << endl;   >>>> 1
      cout << std::alignment_of<B>::value << endl;   >>>> 2

    1.3 std::aligned_storage

      std::aligned_storage可以看成一个内存对其的缓冲区,原型如下:

      template<std::size_t Len, std::size_t Align = /*default-alignment*/>

      struct aligned_storage;

      Len表示所存储类型的sie,Align表示该类型的内存对齐大小

    1.4 max_align_t和std::align

      std::max_align_t用来返回当前平台的最大默认内存对齐类型,对于malloc返回的内存,其对齐和max_align_t类型的对齐大小应当是一致的。我们可以通过下面的方式获得当前平台的最大默认内存对齐数:

      std::cout << alignof(std::max_align_t) << std::endl;

      std::align用来在一大块内存中获取一个符合指定内存要求的地址

    char buffer[] = "......";
    void *ptr = buffer;
    std::size_t space = sizeof(buffer) - 1;
    std::align(alignof(int),sizeof(char),pt,space);

    2. 示例

    2.1. optional类实现

    // 实现boost中的optional类
    // 该类可以存储任意类型的数据
    // int float string struct
    
    #pragma once
    using namespace std;
    
    template <typename T>
    class COptional
    {
    public:
        // alignof是vs2013ctp中才支持的版本,如果没有该版本,用alignedment_of<T>::value代替
        //typedef aligned_storage<sizeof(T), alignof(T)>::type AligendT;
        using AligendT = typename aligned_storage<sizeof(T), alignment_of<T>::value>::type;
    
        COptional(){}
        COptional(const T &t)
        {
            Create(t);
        }
        COptional(const COptional& other)
        {
            if (other.IsInit())
            {
                Assign(other);
            }
        }
        ~COptional()
        {
            if (IsInit())
            {
                Destroy();
            }
        }
    
        const T & operator*() const
        {
            if (IsInit())
            {
                return *((T *)(&m_Data));
            }
            cout << "is not init!" << endl;
        }
    
        // 根据参数创建
        template<typename ...ARGS>
        void Emplace(ARGS&& ...Args)
        {
            Destroy();
            Create(forward<ARGS>(Args)...);
        }
    
    private:
        template <typename ...ARGS>
        void Create(ARGS&& ...Args)
        {
            new (&m_Data) T(forward<ARGS>(Args)...);  // placement new 创建
            m_bInit = true;
        }
    
        // 销毁缓冲区对象
        void Destroy()
        {
            if (m_bInit)
            {
                m_bInit = false;
                ((T *)(&m_Data))->~T();
            }
        }
    
        bool IsInit() const
        {
            return m_bInit;
        }
    
        void Assign(const COptional& other)
        {
            if (other.IsInit())
            {
                Destroy();
                new (&m_Data) (T)*((T*)(&other.m_Data));
                m_bInit = true;
            }
            Destroy();
        }
    private:
        AligendT m_Data;
        bool m_bInit = false;
    };

    2.2. 惰性求值类lazy类实现

    #pragma once
    
    #include<type_traits>
    #include<boostoptional.hpp>
    
    using namespace std;
    
    // 实现懒惰求值类lazy
    template<typename T>
    class CLazy
    {
    public:
        CLazy(){}
    
        template<typename FUN, typename ...ARG>
        CLazy(FUN &fun, ARG ...args)
        {
            std::cout << "参数个数:" << sizeof ...(args) << std::endl;
            m_fun = [&fun, args...]{return fun(args...); };
        }
    
        T &Value()
        {
            if (!m_Value.is_initialized())
            {
                m_Value = m_fun();   // 隐士转换
            }
    
            return *m_Value;
        }
    
        bool IsCreated() const
        {
            return m_Value.is_initialized();
        }
    
    private:
        std::function<T()> m_fun;
        boost::optional<T> m_Value;
    };

    3. 测试

    #include "stdio.h"
    
    #include "lazy.h"
    
    #include<iostream>
    using namespace std;
    
    #include "optionalex.h"
    
    int foo(int x)
    {
        cout << "函数名:" << __FUNCTION__ << endl;
        return 2 * x;
    }
    
    float fooadd(int x, int y, float z)
    {
        cout << "函数名:" << __FUNCTION__ << endl;
        return x + y+z;
    }
    
    template<typename FUN, typename ...ARG>
    CLazy<typename result_of<FUN(ARG...)>::type> lazy(FUN && fun, ARG && ...args)
    {
        return CLazy<typename result_of<FUN(ARG...)>::type>(forward<FUN>(fun), forward<ARG>(args)...);
    }
    
    struct test
    {
        int a;
        float b;
        test(int aa, float bb) :a(aa), b(bb){}
        friend ostream& operator<<(ostream& os, const test& other)
        {
            os << other.a << " " << other.b << endl;
            return os;
        }
    };
    void main()
    {
        cout << "COptional类测试1,当对象没初始化:" << endl;
        COptional<int> op1;
        cout << "输出:" << *op1 << endl;
    
        cout << "COptional类测试2,int类型:" << endl;
        COptional<int> op2 = 99;
        cout << "输出:" << *op2 << endl;
    
        cout << "COptional类测试3,float类型:" << endl;
        COptional<float> op3 = 12.453;
        cout << "输出:" << *op3 << endl;
        
        cout << "COptional类测试4,struct类型:" << endl;
        COptional<test> op4 = test(8, 9.8);
        cout << "输出:" << *op4 << endl;
    
        cout << "lazy类测试:" << endl;
        CLazy<int> lazy1(foo, 2);
        cout << lazy1.Value() << endl;
        CLazy<float> lazy22(fooadd, 2, 4, 6.2);
        cout << lazy22.Value() << endl;
        cout << lazy([](int a, int b){return a + b; }, 10, 22).Value() << endl;
    }

  • 相关阅读:
    EF ObjectQuery查询及方法
    Entity Framework --Entity SQL注意事项
    EF中Entity SQL用法
    Navicat for Oracle设置唯一性和递增序列
    Oracle添加自增长字段方法步骤
    MVC5项目中添加Wep API
    C#版 Winform界面 Socket编程 Client客户端
    C#版 Winform界面 Socket编程 Server服务器端
    给缺少Python项目实战经验的人
    python模块之collections
  • 原文地址:https://www.cnblogs.com/xiaobingqianrui/p/9068226.html
Copyright © 2011-2022 走看看