auto
自动推导类型。
auto i = 10;
std::cout << i << std::endl;
double x = 12.34;
auto *y = new auto(x);
std::cout << *y << std::endl;
decltype
可以获取变量或值的类型名称,替换源码中的调用。
int x = 0;
decltype(x) y = x;
nullptr
空指针,指向地址0x000000的指针。与NULL的区别是,NULL是0的别名,原型为:#define NULL 0,调用NULL的地方相当于直接替换为0。
智能指针
#include <stdlib.h>
#include <iostream>
#include <memory>
void main(){
// 建议在for前后断点观察进程占用内存
for (int i = 0; i < 1000000; ++i)
{
double* p = new double;
std::auto_ptr<double> ap (p); //C++98中的智能指针,依赖一个原生指针。在块结束时释放指针指向内存,相当于把堆当栈使用。
}
for (int i = 0; i < 1000000; ++i)
{
std::unique_ptr<double> ap (new double); //C++11中的智能指针,可直接使用原生指针初始化,当指针不被引用时释放指针指向内存。
}
system("pause");
}
高级for
int arr[] = {1,2,3,4,5};
for( int i : arr ){
std::cout<<i<<std::endl;
}
lambda表达式
lambda式的作用类似Java中的创建一个匿名函数对象。这样就可以省去定义很多只有一处地方使用的函数。
lambda表达式格式:[ 可访问外部变量列表 ]( 参数列表 ) ->返回值类型 {
函数体
}
std::array<int>(5) arr = {1,2,3,4,5};
int a = 1;
int b = 2;
//1.访问指定外部变量的右值(右值在寄存器,不在内存,不存在地址,所以不能执行赋值操作)
for_each(arr.begin(), arr.end(), [ a, b ] ( int & i ) {
std::cout<<a<<std::endl;
std::cout<<b<<std::endl;
//a = b; //error
})
//2.访问所有外部变量的右值
for_each(arr.begin(), arr.end(), [ = ] ( int & i ) {
std::cout<<a<<std::endl;
std::cout<<b<<std::endl;
})
//3.访问指定外部变量的左值
for_each(arr.begin(), arr.end(), [ &a, &b ] ( int & i ) {
a = b = i;
std::cout<<a<<std::endl;
std::cout<<b<<std::endl;
})
//4.访问所有外部变量的左值
for_each(arr.begin(), arr.end(), [ & ] ( int & i ) {
a = b = i;
std::cout<<a<<std::endl;
std::cout<<b<<std::endl;
})
//5.定义一个有返回值的lambda表达式
auto fun = [ ] ( int & a , int & b) ->int {
return a+b;
})
int result = fun(arr[0], arr[0]);
tuple
tuple是一个多元组,可以包含多个不同类型的数据。
// tuple example
#include <iostream> // std::cout
#include <tuple> // std::tuple, std::get, std::tie, std::ignore
int main ()
{
std::tuple<int,char> foo (10,'x');
auto bar = std::make_tuple ("test", 3.1, 14, 'y');
std::get<2>(bar) = 100; // 访问tuple中的元素
int myint; char mychar;
std::tie (myint, mychar) = foo; // unpack elements
std::tie (std::ignore, std::ignore, myint, mychar) = bar; // unpack (with ignore),std::ignore用于忽略指定位置的元素
mychar = std::get<3>(bar);
std::get<0>(foo) = std::get<2>(bar);
std::get<1>(foo) = mychar;
std::cout << "foo contains: ";
std::cout << std::get<0>(foo) << ' ';
std::cout << std::get<1>(foo) << '\n';
return 0;
}
可变参数列表
#include<cstdarg> //用于处理可变参数列表的库
template<typename T>
T sum(int count, T data1, ...) // data1用于限定可变参数列表至少需要一个参数
{
va_list arg_ptr; //定义可变参数列表指针
va_start(arg_ptr, count); //初始化可变参数列表,限定从count后面开始
T total = 0;
for(int i=0; i<count; ++i){
total += va_arg(arg_ptr, T); // 取可变参数列表中的参数进行累加
}
va_end(arg_ptr); //结束可变参数列表指针的使用
return total;
}
可变参数模板
#include<iostream>
template<typename... Arguments>
void func(const Arguments&... args)
{
const unsigned size= sizeof...(Arguments); // sizeof...操作符可获取可变参数列表的参数个数
std::cout << size<< std::endl;
printf(args...);
}
void main(){
func("%d%d%d%d",1, 2, 3, 4);
}
使用{}初始化
在C++11之前,只有数组可以使用{}初始化。C++11之后stl中的容器也可以使用{}初始化了。
//C++11 之前:
std::map<int,string> map;
map[1] = "a";
map[2] = "b";
//C++11之后:
std::map<int,string> map = { {1,"a"}, {2,"b"} };
类成员变量初始化默认值
在C++11之前,类的成员变量如果想初始化一个默认值只能通过构造函数去初始化,但如果有多个构造函数,这时初始化就变得麻烦了,每个构造都需要初始化,或者通过一个构造调用另一构造方式初始化。
C++11之前
class A{
private:
int i;
public:
A():i(1){} //初始化i为1
A(string str):i(1){} //初始化i为1
};
或
class A{
private:
int i;
public:
A() :i(1){} //初始化i为1
A(string str):A(){ } //调用空构造,初始化i为1
};
在C++11之后
class A{
private:
int i = 1; //给成员变量设置默认初始值
public:
A(){}
A(string str){}
};