在Linux下编译C++11
#include<typeinfo> int main() { auto a=10; cout<<typeid(a).name()<<endl; //得到a的类型,只是一个字符串 return 0; }
编译需要加-std=c++11,如下例:
auto
C++11中引入auto第一种作用是为了自动类型推导
auto的自动类型推导,用于从初始化表达式中推断出变量的数据类型。通过auto的自动类型推导,可以大大简化我们的编程工作
auto实际上实在编译时对变量进行了类型推导,所以不会对程序的运行效率造成不良影响
另外,似乎auto并不会影响编译速度,因为编译时本来也要右侧推导然后判断与左侧是否匹配。
auto a; // 错误,auto是通过初始化表达式进行类型推导,如果没有初始化表达式,就无法确定a的类型 auto i = 1; auto d = 1.0; auto str = "Hello World"; auto ch = 'A'; auto func = less<int>(); vector<int> iv; auto ite = iv.begin(); auto p = new foo() // 对自定义类型进行类型推导
auto不光有以上的应用,它在模板中也是大显身手,比如下例这个加工产品的例子中,如果不使用auto就必须声明Product这一模板参数:
template <typename Product, typename Creator> void processProduct(const Creator& creator) { Product* val = creator.makeObject(); // do somthing with val }
template <typename Creator> void processProduct(const Creator& creator) { auto val = creator.makeObject(); // do somthing with val }
抛弃了麻烦的模板参数,整个代码变得更加正解了。
decltype
decltype实际上有点像auto的反函数,auto可以让你声明一个变量,而decltype则可以从一个变量或表达式中得到类型,有实例如下:
int x = 3; decltype(x) y = x;
template <typename Creator> auto processProduct(const Creator& creator) -> decltype(creator.makeObject()) { auto val = creator.makeObject(); // do somthing with val }
typeid().name()与decltype
typeid().name得到的仅仅是一个字符串
而decltype可以提取出类型
nullptr
nullptr是为了解决原来C++中NULL的二义性问题而引进的一种新的类型,因为NULL实际上代表的是0
void F(int a){ cout<<a<<endl; } void F(int *p){ assert(p != NULL); cout<< p <<endl; } int main(){ int *p = nullptr; int *q = NULL; bool equal = ( p == q ); // equal的值为true,说明p和q都是空指针 int a = nullptr; // 编译失败,nullptr不能转型为int F(0); // 在C++98中编译失败,有二义性;在C++11中调用F(int) F(nullptr); return 0; }
序列for循环
在C++中for循环可以使用类似java的简化的for循环,可以用于遍历数组,容器,string以及由begin和end函数定义的序列(即有Iterator),示例代码如下:
map<string, int> m{{"a", 1}, {"b", 2}, {"c", 3}}; for (auto p : m){ cout<<p.first<<" : "<<p.second<<endl; }
更加优雅的初始化
在引入C++11之前,只有数组能使用初始化列表,其他容器想要使用初始化列表,只能用以下方法:
int arr[3] = {1, 2, 3}; vector<int> v(arr, arr + 3);
在C++11中,我们可以使用以下语法来进行替换:
int arr[3]{1, 2, 3}; vector<int> iv{1, 2, 3}; map<int, string>{{1, "a"}, {2, "b"}}; string str{"Hello World"};
alignof和alignas
C++11标准中,为了支持对齐,引入了两个关键字:操作符alignof和对齐描述符alignas。
操作符alignof:用于返回类的对齐方式,即对齐值
对齐描述符alignas:用于设置类使用哪种对齐方式
struct alignas(32) A { char a; int b; }; int main() { //由于用alignas设置了对齐方式,原本大小为8字节的类A变为32字节了 cout << sizeof(A) << endl; //输出:32 cout << alignof(A) << endl; //输出:32 //alignas既可以接受常量表达式,也可以接受类型作为参数 alignas(8) int a; alignas(alignof(double)) int b; }
C++11标准中规定了一个“基本对齐值”。一般情况下其值等于平台上支持的最大标量类型数据的对齐值。我们可以通过alignof(std::max_align_t)来查询其值。而像之前我们把对齐值设置为32位的做法称为扩展对齐,这按照C++标准该程序是不规范的,可能会导致未知的编译错误或者运行时错误。
其余对齐方式有STL库函数(std::align),还有STL库模板类型(aligned_storage和aligned_union)。