c++11学习(逐步更新。。)

template 两个用途:

1.常见的在模板定义的开始,比如template<typename ...Args>

2.模板类内部定义了模板成员函数或者嵌套的成员模板类。比如:

template<typename ...Args>
class TeTest
{
public:
    
    bool is()const
    {
        return true;
    }
};
template<typename T>
class TeFunc
{
protected:
    using Value = TeTest<T>;
    Value value;
    
protected:
    bool isValue()const
    {
        return value.template is();
    }
};
//继承自stl中的容器 比如vector
template <typename T, template <typename> class Cont = std::vector>
class Test : public Cont<point<T>>
{
public:
    
};

限制模板形参类型

//方法一
template<typename T>
typename std::enable_if<std::is_integral<T>::value,bool>::type
is_inte(T i)
{
    return bool(i % 2);
}

//方法二
template < class T,
           class = typename std::enable_if<std::is_integral<T>::value>::type>
bool is_oht(T i)
{
    return bool(i%2);
}

 

1.static_assert

不同于assert,static_assert是在编译期就检查表达式为真或非零,而assert是在程序运行期才检查

 

 static_assert(sizeof(void *) == 4, "64-bit code generation is not supported.");

2.不定参数模板

 

template<typename T>
void printT(T t)
{
    cout << t << " ";
}
template<typename T, typename ...Args>
void printT(T t, Args ...args)
{
    printT(t);
    printT(args...);
}
template<typename ...Args>
void clacSize(Args ...args)
{
    cout << "size:" << sizeof...(args) << endl;
}
int main()
{
    printT(10,123,"hello world.");
    cout << endl;
    clacSize("hello"," world", 100, 10, 1);
}

output:

10 123 hello world. 
size:5

3.元组(不同类型值的集合)

 

template<typename T>
void output(const T &t)
{
    cout << t << endl;
}
template<typename T ,typename... Args>
void output(const T &a, Args... arg)
{
    cout << a << endl;
    output(arg...);
}
template<typename... T>
std::tuple<T...> getDD(T... aa)
{
    return std::make_tuple(aa...);
}


template<typename TT,std::size_t N>
struct TuplePrinter{
static void print(const TT &value)
{
    TuplePrinter<TT, N - 1>::print(value);
    cout << "," << std::get<N-1>(value);
}
};
template<typename T>
struct TuplePrinter<T,1>{
static void print(const T &t)
{
    cout << std::get<0>(t) ;
}
};
template<typename ... Args>
void PrintTuple(const std::tuple<Args...> &t)
{
    TuplePrinter<decltype(t), sizeof...(Args)>::print(t);
}
int main(void)
{
    auto vv = getDD(10,11);
    cout << "num = " << std::tuple_size<decltype(vv)>::value << endl;
    output(std::get<0>(vv), std::get<1>(vv));
    auto cc = std::tie("test","world");//
    cout << std::get<0>(cc) << endl;
    
    auto oo = std::tuple_cat(vv, cc);
    PrintTuple(oo);
    cout << endl;
    return 0;
}

result:
num = 2
10
11
test
10,11,test,world

4.auto

自动推导

	auto a = 12;auto b = 12.0f;auto c = true;auto d = [] (int x)->int{ return 12;};auto e = std::bind(&func, _1);


或者函数,可以根据传入类型,推导出函数返回类型

 

template <typename _Tx, typename _Ty> auto multiply(_Tx x, _Ty y)->decltype(_Tx*_Ty) { return x*y; }

 

5.std::is_same std::is_convertible

std::is_same 是判断两个类型是否相等

std::is_convertible是拍单两个类型是否是继承关系

 

 cout <<  std::is_same<int, char>::value;
result:0

class One
{
    
};http://write.blog.csdn.net/postedit/53640611
class Two : public One
{
    
};
cout << std::is_convertible<Two, One>::value << endl;
cout << std::is_convertible<One, Two>::value << endl;
result:
0
1

 

6.内存对齐

內存对齐的作用:

1. 平台原因(移植原因):不是所有的硬件凭条都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。

2. 性能原因:经过内存对齐后,CPU的内存访问速度大大提升。由于CPU把内存当成是一块一块的,块的大小可以是2、4、8、16字节大小,因此CPU在读取内存时是一块

一块进行读取的。所以如果字节不对齐,有可能会出现比如一个int类型位于两块内存中,这样cpu就要读取两块,这就进行了额外的操作,大大降低了CPU的性能

alignas(4) char t;

alignas(int) char c;

cout << alignof(t) << endl;

alignas只能改大内存对齐,改小必须使用#param pack(1)

std::alignment_of 补足alignof的功能不仅可以返回值还提供操作

std::aligned_storage 使用其可以用来创建对应内存对齐类型的对象

 

    std::aligned_storage<sizeof(MyStruct), alignof(MyStruct)>::type xx;  
    ::new (&xx) MyStruct;  

注意:在使用堆内存时,可能还是需要align_malloc,因为现在new并不能保证在超出最大默认对齐后,还能保证对齐是正确的如:

 

 

    struct alignas(32) MyStruct  
    {  
        char a;         // 1 byte  
        int b;          // 4 bytes  
        short c;        // 2 bytes  
        long long d;    // 8 bytes  
        char e;         // 1 byte  
    };  
       
    void* p = new MyStruct;  
    // warning C4316: 'MyStruct' : object allocated on the heap may not be aligned 32  


返回当前平台默认最大对齐数

 

 

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


std::align是用来在一大块内存中返回一个符合对齐要求的地址

 

 

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


在buffer这个 alignof(int)对齐的内存中,找一个char大小的内存将地址存入pt中,并记录由pt开始的长度到space中

 

 

 

 

7.std::move,std::forward

这个函数并不是做移位操作,而是将左值转换成右值。c++11 类中除了构造、拷贝之外还有一种名为移动构造函数的 形式

格式如下

XXX(XXX&&)

当源对象所有权都交由目标对象的时候,就可以调用移动构造函数。

std::move会调用移动构造函数。

std::move 和 std::forward 仅仅进行转换的函数,std::move无条件转换为右值,而forward是把参数在有绑定右值的时候才转换, 二者在runtime时不做任何事

 

8.decltype,std::declval,std::result_of

 

decltype:关键字,返回表达式类型

std::declval:常配合decltype, 而且不通过构造函数返回引用类型

std::result_of:返回函数返回类型

 

struct Person
{
    std::string name;
    int         code;
    int         value;
};

template<typename Ty>
class Range
{
public:
    typedef typename Ty::value_type value_type;
    Range(const Ty &t):_t(t)
    {
        
    }
    
    
    template<typename Fn>
    std::multimap<typename std::result_of<Fn(value_type)>::type, value_type>  groupBy(Fn fn)
    {
        typedef decltype(std::declval<Fn>()(std::declval<value_type>())) key_type;
        std::multimap<key_type, value_type>   maps;
        std::for_each(begin(_t), end(_t), [&maps,&fn](const value_type &item)
                      {
                          maps.insert(std::make_pair(fn(item), item));
                      });
        return maps;
    }
    
private:
    Ty _t;
};
int main(int argc, const char * argv[])
{
    std::vector<Person>  pers = {{"aa",10,23},{"bb",13,24},{"aa",10,25},{"bb",13,25}};
        
    Range< std::vector<Person> >  ranges(pers);
    auto a1 = ranges.groupBy([](const Person &person)
    {
        return person.code;
    });
    auto a2 = ranges.groupBy([](const Person &person)
    {
        return person.name;
    });
    PrintMap(a1,a2);
    
    return 0;
} 

 

template<typename T1, typename T2>
auto sum(T1 t1, T2 t2)->decltype(t1 + t2)
{
    return t1 + t2;
}

 

 

 

9.std::remove_reference

若为引用或右值类型则取出其左值类型  ,若为值类型,则返回值类型

 

 

template<class T1, class T2>
void print_is_same() {
  std::cout << std::is_same<T1, T2>() << '\n';
}
 
int main() {
  std::cout << std::boolalpha;
 
  print_is_same<int, int>();    // true
  print_is_same<int, int &>();  // false
  print_is_same<int, int &&>(); // false
 
  print_is_same<int, std::remove_reference<int>::type>();    // true
  print_is_same<int, std::remove_reference<int &>::type>();  // true
  print_is_same<int, std::remove_reference<int &&>::type>(); // true
}

 

10.constexpr

 

   a.用constexpr修饰函数将限制函数的行为。首先,该函数的回返值类型不能为void。第二,函数的内容必须依照"returnexpr"的形式。第三,在参数替换后,expr必须是个常数表示式。这些常数表示式只能够调用其他被定义为constexpr的函数,或是其他常数表示式的数据参数。最后,有着这样修饰符的函数直到在该编译单元内被定义之前是不能够被调用的

   b.constexpr解除了除了变量必须是整型或枚举类型的限制,constexpr double test = 10.0;

   c.为了让用户自定义类型(user-defined type)参与构造常量表示式,构造函数也可以用constexpr来声明

 

11.override,final,nullptr

 

   override子类重载函数,final申明类不可被继承   class Test final{};,nullptr 空指针

12.强类型枚举

 

enum class myEnumeration
{
  Val1,
  Val2,
  Val3 = 100,
  Val4 /* = 101 */,
};
不能与int相互转换了

enum class Enum2 : unsigned int {Val1, Val2};

也可以定义成别的类

13.std::initializer_list

 

允许数组初始化列表

 

void FunctionName(std::initializer_list<float> list);

FunctionName({1.0f, -3.45f, -0.4f});

14.std::addressof

  返回变量/引用等变量的物理地址

15.读取文本文件全部内容

//function 1.
std::ifstream file(path,ios::in);
std::string str((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());

//function 2.
std::ifstream file(path,ios::in);
std::stringstream ss;
ss << file.rdbuf();
std::string contents(ss.str());

15.多线程

 

http://www.cnblogs.com/haippy/p/3284540.html

 

 

 

 

 

 

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值