统一初始化
c++扩大了用{}的使用范围,使其可用于内置类型和自定义类型
缩窄
初始化列表语法可防止缩窄,即禁止将数值赋给无法存储它的数值变量; 在编译器会报错
std::initializer_list
C++11提供了模板类initializer_list,可将其用作构造函数的参数
code
# include <iostream>
# include <cstring>
# include <memory>
# include <vector>
using namespace std;
# define cout ( cout << "line " << __LINE__ << " - " )
class MyClass
{
private :
int m_a;
double m_b;
public :
MyClass ( ) = default ;
MyClass ( int a, double b) : m_a ( a) , m_b ( b) { }
} ;
int main ( )
{
{
int x = { 5 } ;
short y[ 5 ] = { 1 , 2 , 3 , 4 , 5 } ;
int * p = new int [ 4 ] { 1 , 2 , 3 , 4 } ;
MyClass a1 ( 1 , 3 ) ;
MyClass a2{ 1 , 2 } ;
MyClass a3 = { 1 , 2 } ;
}
{
char c3 = static_cast < char > ( 1.23e27 ) ;
}
{
vector< int > a ( 10 ) ;
vector< int > b{ 10 } ;
vector< int > c{ 1 , 2 , 3 } ;
}
return 0 ;
}
返回顶部
声明
C++11提供了多种简化声明的功能,尤其在使用模板时
auto
C++11将其用于实现自动类型推断;这要求进行显式初始化,让编译器能够将变量的类型设置为初始值的类型,可以简化代码
decltype
关键字decltype将变量的类型声明为表达式指定的类型,在定义模版的时候特别有用
返回类型后置
C++11新增了一种函数声明语法:在函数名和参数列表后面(而不是前面)指定返回类型
模版别名:using=
using = 和typedef区别
都可以创建类型别名 using=可以用于模版部分具体化,但是typedef不能
nullptr
空指针是不会指向有效数据的指针 以前c++源码中使用0表示这种指针,但内部表示可能不同;使得0即可表示指针常量,又可表示整型常量 现阶段:如果试图将nullptr传递给int形参的函数,编译器将此视为错误 建议:出于清晰和安全考虑,空指针请使用nullptr—如果您的编译器支持它 返回顶部
code
# include <iostream>
# include <algorithm>
# include <memory>
# include <vector>
# include <array>
using namespace std;
# define cout ( cout << "line " << __LINE__ << " - " )
class MyClass
{
private :
int m_a;
double m_b;
public :
MyClass ( ) = default ;
MyClass ( int a, double b) : m_a ( a) , m_b ( b) { }
} ;
template < typename T , typename U >
void mul ( T a, U b)
{
decltype ( a * b) tu;
tu = a * b;
cout << tu << '\t' << typeid ( tu) . name ( ) << endl;
}
template < typename T , typename U >
auto myAdd ( T a, U b) -> decltype ( a + b)
{
return a + b;
}
template < typename T >
using arr10 = array< T, 10 > ;
void testAuto ( )
{
auto a = 5 ;
auto b = 5.0 ;
vector< int > c{ 1 , 2 , 3 } ;
auto it = c. begin ( ) ;
auto f = [ ] ( int a) -> int {
return a + 2 ;
} ;
}
void testDecltype ( )
{
const int x = 5 ;
decltype ( x) y = 6 ;
cout << typeid ( y) . name ( ) << endl;
mul < char , short > ( char ( 1 ) , short ( 2 ) ) ;
}
void testRearDecl ( )
{
auto a = myAdd < int , double > ( int ( 5 ) , double ( 10.0 ) ) ;
cout << a << '\t' << typeid ( a) . name ( ) << endl;
}
void testUsing ( )
{
using vi = vector< int > ;
vi vec{ 1 , 2 , 3 } ;
arr10< int > b = { 1 , 2 , 3 } ;
for_each ( b. begin ( ) , b. end ( ) , [ ] ( const int & n) { cout << n << '\t' ; } ) ;
cout << endl;
}
void print ( int * p)
{
cout << p << '\t' << ( nullptr == p ? - 1 : * p) << endl;
}
void testNullptr ( )
{
int * p = nullptr ;
cout << p << '\t' << typeid ( p) . name ( ) << endl;
print ( nullptr ) ;
print ( 0 ) ;
}
int main ( )
{
testAuto ( ) ;
testDecltype ( ) ;
testRearDecl ( ) ;
testUsing ( ) ;
testNullptr ( ) ;
return 0 ;
}
智能指针
c++11之智能指针
返回顶部
异常规范方面的修改
noexcept 告诉编译器,函数中不会发生异常,有利于编译器对程序作更多的优化 通过noexcept 代替throw() noexcept 默认为noexcept(true) 析构函数不能抛出异常:Effective C++ 里面有一条”别让异常逃离析构函数“,大意说是Don’t do that, otherwise the behavior is undefined;其它异常抛出时在栈解退阶段 无法捕捉析构里的异常 构造函数抛出异常注意内存泄漏 tips: 析构函数/移动构造/移动赋值函数加上 noexcept
code
# include <iostream>
# include <algorithm>
# include <memory>
# include <vector>
# include <array>
using namespace std;
# define cout ( cout << "line " << __LINE__ << " - " )
void print ( int a) throw ( )
{
cout << a << endl;
}
void print2 ( int a) noexcept
{
cout << a << endl;
}
template < typename T >
void mySwap ( T & a, T & b) noexcept ( noexcept ( a. swap ( b) ) )
{
a. swap ( b) ;
}
class Base
{
public :
void fun ( ) { throw logic_error ( "1" ) ; }
~ Base ( ) noexcept ( false )
{
cout << "destruct base" << endl;
throw logic_error ( "2" ) ;
}
} ;
void testDestructExcept ( )
{
try
{
Base base;
}
catch ( exception & e)
{
cout << e. what ( ) << endl;
}
catch ( . . . )
{
cout << "get the catch" << endl;
}
}
int main ( )
{
testDestructExcept ( ) ;
return 0 ;
}
返回顶部
作用域内枚举
C++11新增了一种枚举。这种枚举使用class或struct定义,以免发生名称冲突
code
# include <iostream>
# include <algorithm>
# include <memory>
# include <vector>
# include <array>
using namespace std;
# define cout ( cout << "line " << __LINE__ << " - " )
enum old
{
NUM1,
NUM2,
NUM3
} ;
enum class new1
{
N1,
N2,
N3
} ;
enum struct new2
{
N1,
N2,
N3
} ;
int main ( )
{
cout << NUM2 << '\t' << int ( new1:: N2) << '\t' << int ( new2:: N2) << '\t' << endl;
return 0 ;
}
返回顶部
对类的修改
显式转换运算符
C++引入了关键字explicit,以禁止单参数构造函数导致的自动转换;防止自动类型转换可能导致意外转换的问题
类内成员初始化
通过使用类内初始化,可避免在构造函数中编写重复的代码,从而降低了程序员的工作量、厌倦情绪和出错的机会
返回顶部
模版和STL方面的修改
基于范围的for循环
形式:for(auto i:std::vector{1,2,3}){}
新的STL容器
C++11新增了STL容器forward_list、unordered_map、unordered_multimap、unordered_set和unordered_multiset,以及模版array
新的STL方法
C++11新增了STL方法cbegin()和cend()
valarray升级
模板valarray独立于STL开发的,C++11添加了两个函数(begin()和end()),它们都接受valarray作为参数
code
# include <iostream>
# include <algorithm>
# include <valarray>
using namespace std;
int main ( )
{
valarray< int > f ( 5 ) ;
valarray< int > a ( f[ slice ( 0 , 4 , 1 ) ] ) ;
for ( auto it : a)
{
cout << it << '\t' ;
}
cout << endl;
return 0 ;
}
摒弃export
C++98新增了关键字export,旨在提供一种途径,让程序员能够将模板定义放在接口文件和实现文件中,其中前者包含原型和模板声明,而后者包含模板函数和方法的定义。实践证明这不现实,因此C++11终止了这种用法,但仍保留了关键字export,供以后使用
尖括号
old-- std::vector<std::list > v1;// 两个>中间多个空格 new–std::vector<std::list> v1;// 两个>中间可以不要空格
返回顶部
右值引用和移动语义
右值引用
作用:可关联到右值,即可出现在赋值表达式右边,但不能对其应用地址运算符 形式:int&& a = 10; 包括:
移动语义
作用:减少资源的拷贝,只改变指向,不拷贝资源 学习移动语义的作用:对大多数程序员来说,右值引用带来的主要好处并非是让他们能够编写使用右值引用的代码,而是能够使用利用右值引用实现移动语义的库代码。例如,STL类现在都有复制构造函数、移动构造函数、复制赋值运算符和移动赋值运算符 通过右值引用实现,编写移动(构造/赋值)函数
code
# include <iostream>
using namespace std;
class Useless
{
private :
int n;
char * pc;
static int ct;
void ShowObject ( ) const ;
public :
Useless ( ) ;
explicit Useless ( int k) ;
explicit Useless ( int k, char ch) ;
Useless ( const Useless & f) ;
Useless ( Useless && f) ;
Useless & operator = ( const Useless & f) ;
Useless & operator = ( Useless && f) ;
~ Useless ( ) ;
Useless operator + ( const Useless & f) const ;
void ShowData ( ) const ;
} ;
int Useless:: ct = 0 ;
Useless :: Useless ( )
{
++ ct;
n = 0 ;
pc = nullptr ;
cout << "default constructor called; number of objects: " << ct << endl;
ShowObject ( ) ;
}
Useless :: Useless ( int k) : n ( k)
{
++ ct;
cout << "int constructor called; number of objects: " << ct << endl;
pc = new char [ n] ;
ShowObject ( ) ;
}
Useless :: Useless ( int k, char ch) : n ( k)
{
++ ct;
cout << "int,char constructor called; number of objects: " << ct << endl;
pc = new char [ n] ;
for ( int i = 0 ; i < n; i++ )
pc[ i] = ch;
ShowObject ( ) ;
}
Useless :: Useless ( const Useless & f) : n ( f. n)
{
++ ct;
cout << "copy const called; number of objects: " << ct << endl;
pc = new char [ n] ;
for ( int i = 0 ; i < n; i++ )
pc[ i] = f. pc[ i] ;
ShowObject ( ) ;
}
Useless :: Useless ( Useless && f) : n ( f. n)
{
++ ct;
cout << "move constructor called;number of objects: " << ct << endl;
pc = f. pc;
f. pc = nullptr ;
f. n = 0 ;
ShowObject ( ) ;
}
Useless & Useless:: operator = ( const Useless & f)
{
cout << "copy operator= called;number of objects: " << ct << endl;
if ( this == & f)
return * this ;
delete [ ] pc;
n = f. n;
pc = new char [ n] ;
for ( int i = 0 ; i < n; i++ )
pc[ i] = f. pc[ i] ;
return * this ;
}
Useless & Useless:: operator = ( Useless && f)
{
cout << "move operator= called;number of objects: " << ct << endl;
if ( this == & f)
return * this ;
delete [ ] pc;
n = f. n;
pc = f. pc;
f. n = 0 ;
f. pc = nullptr ;
return * this ;
}
Useless :: ~ Useless ( )
{
cout << "destructor called; objects left: " << -- ct << endl;
cout << "delete object:" << endl;
ShowObject ( ) ;
delete [ ] pc;
}
Useless Useless:: operator + ( const Useless & f) const
{
cout << "Enterint operator+()" << endl;
Useless temp = Useless ( n + f. n) ;
for ( int i = 0 ; i < n; i++ )
temp. pc[ i] = pc[ i] ;
for ( int i = n; i < temp. n; i++ )
temp. pc[ i] = f. pc[ i - n] ;
cout << "tempt object: " << endl;
cout << "Leaving operator + ()" << endl;
return temp;
}
void Useless :: ShowObject ( ) const
{
cout << "Number of elements: " << n << '\t' ;
cout << "Data address: " << ( void * ) pc << endl;
}
void Useless :: ShowData ( ) const
{
if ( 0 == n)
cout << "(object empty)" ;
else
for ( int i = 0 ; i < n; i++ )
cout << pc[ i] ;
cout << endl;
}
int main ( )
{
Useless one ( 10 , 'x' ) ;
Useless two = one;
Useless three ( 20 , 'o' ) ;
Useless four = one + three;
cout << "object one: " ;
one. ShowData ( ) ;
cout << "object two: " ;
two. ShowData ( ) ;
cout << "object three:" ;
three. ShowData ( ) ;
cout << "object four:" ;
four. ShowData ( ) ;
four = three;
four = std:: move ( three) ;
return 0 ;
}
返回顶部
新的类功能
特殊的成员函数
c++11新增了两个函数:移动构造函数和移动赋值运算符 tips
如果您提供了析构函数、复制构造函数或复制赋值运算符,编译器将不会自动提供移动构造函数和移动赋值运算符 您提供了移动构造函数,因此编译器不会自动创建默认的构造函数、复制构造函数和复制赋值构造函数
默认的方法和禁用的方法
default:显式地声明这些方法的默认版本,关键字default只能用于6个特殊成员函数 delete:用于禁止编译器使用特定方法,delete可用于任何成员函数
委托构造函数
为让编码工作更简单、更可靠,C++11允许您在一个构造函数的定义中使用另一个构造函数。这被称为委托,因为构造函数暂时将创建对象的工作委托给另一个构造函数 example
# include <iostream>
# include <string>
using namespace std;
# define cout ( cout << "line " << __LINE__ << " - " )
class MyClass
{
private :
int m_a = 0 ;
double m_b = 0.0 ;
string m_c;
public :
MyClass ( int a, double b, string c) : m_a ( a) , m_b ( b) , m_c ( c)
{
}
MyClass ( string c) : MyClass ( 2 , 0.0 , c)
{
}
void show ( )
{
cout << m_a << '\t' << m_b << '\t' << m_c << endl;
}
} ;
int main ( )
{
MyClass a ( "hello" ) ;
a. show ( ) ;
return 0 ;
}
继承构造函数
为进一步简化编码工作,C++11提供了一种让派生类能够继承基类构造函数的机制 code
# include <iostream>
# include <string>
using namespace std;
# define cout ( cout << "line " << __LINE__ << " - " )
class MyClass
{
private :
int m_a = 0 ;
double m_b = 0.0 ;
string m_c;
public :
MyClass ( int a, double b, string c) : m_a ( a) , m_b ( b) , m_c ( c)
{
}
MyClass ( double b) : MyClass ( 1 , b, string ( ) )
{
}
MyClass ( string c) : MyClass ( 2 , 0.0 , c)
{
}
void show ( )
{
cout << m_a << '\t' << m_b << '\t' << m_c << endl;
}
} ;
class MyClassInherit : public MyClass
{
private :
int m_j = 0 ;
public :
using MyClass:: MyClass;
MyClassInherit ( int a) : MyClass ( 2 * a, 0.0 , string ( ) ) , m_j ( a)
{
}
MyClassInherit ( string a) : MyClass ( 0 , 0.0 , a) , m_j ( 2 )
{
}
void show ( )
{
cout << m_j << endl;
MyClass :: show ( ) ;
}
} ;
int main ( )
{
MyClassInherit a ( "hello" ) ;
a. show ( ) ;
MyClassInherit b ( double ( 5.5 ) ) ;
b. show ( ) ;
return 0 ;
}
管理虚方法:override和final
override:指出您要覆盖一个虚函数:将其放在参数列表后面。如果声明与基类方法不匹配,编译器将视为错误 final:禁止派生类覆盖特定的虚方法
返回顶部
lambda函数
主要目的:让您能够将类似于函数的表达式用作接受函数指针或函数符的函数的参数 优点
距离:定义和使用距离可以很近(因为不能在函数内部定义其他函数,因此函数的定义可能离使用它的地方很远。函数符是不错的选择,因为可在函数内部定义类(包含函数符类),因此定义离使用地点可以很近) 简洁:函数符代码比函数和lambda代码更繁琐,函数和lambda的简洁程度相当 效率:取决于编译器使用什么类型来跟踪lambda(函数指针方法阻止了内联,因为编译器传统上不会内联其地址被获取的函数,因为函数地址的概念意味着非内联函数。而函数符和lambda通常不会阻止内联) 功能:lambda有一些额外的功能。具体地说,lambad可访问作用域内的任何动态变量 形式:[capture](parameters)->return-type{body}
返回顶部
包装器/适配器
bind
bind:函数适配器,通过一个可调用对象生成新的可调用对象 其中模板bind可替代以前的bind1st和bind2nd,但更灵活 code
# include <iostream>
# include <functional>
using namespace std;
# define cout ( cout << "line " << __LINE__ << " - " )
void func ( int a, int b, int c)
{
cout << a << '\t' << b << '\t' << c << endl;
}
class MyClass
{
public :
void show ( int a, int b, int c)
{
cout << "MyClass::show:" << '\t' << a << '\t' << b << '\t' << c << endl;
}
} ;
class MyClass2
{
public :
MyClass2 ( ) = default ;
MyClass2 ( int a) : m_a ( a) { }
int operator ( ) ( int a)
{
return m_a * a;
}
private :
int m_a = 10 ;
} ;
int main ( )
{
auto f1 = bind ( func, placeholders:: _2, 15 , placeholders:: _1) ;
f1 ( 12 , 20 ) ;
MyClass a;
auto f2 = bind ( & MyClass:: show, & a, placeholders:: _1, 2 , placeholders:: _2) ;
f2 ( 1 , 3 ) ;
MyClass2 b ( 20 ) ;
cout << b ( 10 ) << endl;
return 0 ;
}
mem_fn
把成员函数转为函数对象,使用对象指针或对象(引用)进行绑定 替换mem_fun/mem_fun_ref code
# include <iostream>
# include <functional>
# include <vector>
using namespace std;
# define cout ( cout << "line " << __LINE__ << " - " )
class MyClass
{
public :
void show ( )
{
cout << "MyClass::show no param" << endl;
}
void print ( int a, int b, int c)
{
cout << "MyClass::show:" << '\t' << a << '\t' << b << '\t' << c << endl;
}
} ;
int main ( )
{
auto f = mem_fn ( & MyClass:: show) ;
f ( MyClass ( ) ) ;
vector< MyClass> vec{ MyClass ( ) , MyClass ( ) , MyClass ( ) } ;
for_each ( vec. begin ( ) , vec. end ( ) , mem_fn ( & MyClass:: show) ) ;
for_each ( vec. begin ( ) , vec. end ( ) , bind ( & MyClass:: print, placeholders:: _1, 1 , 2 , 3 ) ) ;
return 0 ;
}
reference_wrapper
function
std::function是一个函数包装器模版,可以包装任何类型的可调用对象(普通函数,函数对象,lambda,函数指针,类成员函数指针) code
# include <iostream>
# include <functional>
# include <vector>
using namespace std;
template < typename T , typename F >
T use_f ( T v, F f)
{
static int cnt = 0 ;
cnt++ ;
cout << "cnt = " << cnt << '\t' << "&cnt = " << & cnt << endl;
return f ( v) ;
}
class FuncOj1
{
private :
double m_a = 0.0 ;
public :
explicit FuncOj1 ( double a) : m_a ( a) { }
double operator ( ) ( double p) { return m_a * p; }
} ;
class FuncOj2
{
private :
double m_a = 0.0 ;
public :
explicit FuncOj2 ( double a) : m_a ( a) { }
double operator ( ) ( double p) { return m_a * p; }
} ;
double f1 ( double x) { return 2.0 * x; }
double f2 ( double x) { return x * x; }
void Test1 ( )
{
cout << '\t' << __FUNCTION__ << '\t' << endl;
double a = 3.14 ;
cout << use_f ( a, f1) << endl;
cout << use_f ( a, f2) << endl;
cout << use_f ( a, FuncOj1 ( 2.0 ) ) << endl;
cout << use_f ( a, FuncOj2 ( 2.0 ) ) << endl;
cout << use_f ( a, [ ] ( double x) { return 2.0 * x; } ) << endl;
cout << use_f ( a, [ ] ( double x) { return x * x; } ) << endl;
}
void Test2 ( )
{
cout << '\t' << __FUNCTION__ << '\t' << endl;
double a = 3.14 ;
typedef function< double ( double ) > fd_d;
cout << use_f ( a, fd_d ( f1) ) << endl;
cout << use_f ( a, fd_d ( f2) ) << endl;
cout << use_f ( a, fd_d ( FuncOj1 ( 2.0 ) ) ) << endl;
cout << use_f ( a, fd_d ( FuncOj2 ( 2.0 ) ) ) << endl;
cout << use_f ( a, fd_d ( [ ] ( double x) { return 2.0 * x; } ) ) << endl;
cout << use_f ( a, fd_d ( [ ] ( double x) { return x * x; } ) ) << endl;
}
int main ( )
{
Test1 ( ) ;
Test2 ( ) ;
return 0 ;
}
返回顶部
可变参数模版
一个可变参数模板(variadictemplate)就是一个接受可变数目参数的模板函数或模板类 可变数目的参数被称为参数包(parameterpacket)
模板参数包(templateparameterpacket),表示零个或多个模板参数 函数参数包(functionparameterpacket),表示零个或多个函数参 sizeof…运算符:获取参数包中包含多少元素 非可变参数模板比可变参数模板更特例化,因此编译器选择非可变参数版本
包扩展
当…扩展一个包时,我们还要提供用于每个扩展元素的模式(pattern) 扩展一个包就是将它分解为构成的元素,对每个元素应用模式,获得扩展后的列表;扩展中的模式会独立地应用于包中的每个元素
转发参数包
tips:在新标准下,我们可以组合使用可变参数模板与forward机制来编写函数,实现将其实参不变地传递给其他函数 code
template < typename . . . Args>
void func ( Args && . . . args)
{
work ( forward < Args> ( args) . . . ) ;
}
函数可变参数模版 code
# include <iostream>
# include <sstream>
# include <string>
using namespace std;
# define cout ( cout << "line " << __LINE__ << " - " )
template < typename . . . Args>
void func ( const Args & . . . rest)
{
cout << sizeof . . . ( Args) << endl;
cout << sizeof . . . ( rest) << endl;
}
template < typename T >
string string_rep ( const T & t)
{
ostringstream ret;
ret << t << '\t' ;
return ret. str ( ) ;
}
template < typename T >
ostream & myPrint ( ostream & os, const T & t)
{
return os << t << endl;
}
template < typename T , typename . . . Args>
ostream & myPrint ( ostream & os, const T & t, const Args & . . . rest)
{
os << t << "\t" ;
return myPrint ( os, rest. . . ) ;
}
int main ( )
{
int a = 1 ;
double b = 2.0 ;
string c = "hello" ;
func ( a, a, b, c) ;
func ( a, c) ;
myPrint ( cout, a, b, c) ;
myPrint ( cout, a, b) ;
myPrint ( cout, a) ;
return 0 ;
}
类可变参数模版 code
# include <iostream>
# include <type_traits>
# include <memory>
using namespace std;
# define cout ( cout << "line " << __LINE__ << " - " )
template < typename . . . Types>
struct Sum ;
template < typename First , typename . . . Rest>
struct Sum < First, Rest. . . >
{
enum
{
value = Sum< First> :: value + Sum< Rest. . . > :: value
} ;
} ;
template < typename Last >
struct Sum < Last>
{
enum
{
value = sizeof ( Last)
} ;
} ;
int main ( )
{
Sum< int , double , string> aa;
cout << sizeof ( int ) << '\t' << sizeof ( double ) << '\t' << sizeof ( string) << endl;
cout << aa. value << endl;
return 0 ;
}
返回顶部
other
并行编程
thread_local:关键字thread_local将变量声明为静态存储,其持续性与特定线程相关;即定义这种变量的线程过期时,变量也将过期;每 一个线程都拥有一个独立的变量实例 code
# include <iostream>
# include <thread>
using namespace std;
thread_local int g_n = 1 ;
void f ( )
{
g_n++ ;
printf ( "id=%d, n=%d\n" , std:: this_thread:: get_id ( ) , g_n) ;
}
void foo ( )
{
thread_local int i = 0 ;
printf ( "id=%d, n=%d\n" , std:: this_thread:: get_id ( ) , i) ;
i++ ;
}
void f2 ( )
{
foo ( ) ;
foo ( ) ;
}
int main ( )
{
g_n++ ;
f ( ) ;
std:: thread t1 ( f) ;
std:: thread t2 ( f) ;
t1. join ( ) ;
t2. join ( ) ;
f ( ) ;
f2 ( ) ;
std:: thread t4 ( f2) ;
std:: thread t5 ( f2) ;
t4. join ( ) ;
t5. join ( ) ;
return 0 ;
}
新增的库
random:头文件random支持的可扩展随机数库提供了大量比rand()复杂的随机数工具 chrono:头文件chrono提供了处理时间间隔的途径 tuple:头文件tuple支持模板tuple ratio:头文件ratio支持的编译阶段有理数算术库让您能够准确地表示任何有理数,其分子和分母可用最宽的整型表示。它还支持对这些有理数进行算术运算 regex:正则表达式库
低级编程
变化之一是放松了POD(PlainOldData)的要求 允许共用体的成员有构造函数和析构函数,这让共用体更灵活;但保留了其他一些限制,如成员不能有虚函数 C++11解决了内存对齐问题; 要控制对齐方式,可使用说明符alignas constexpr机制让编译器能够在编译阶段计算结果为常量的表达式,让const变量可存储在只读内存中,这对嵌入式编程来说很有用(在运行阶段初始化的变量存储在随机访问内存中)
杂项
C++11提供了一种创建用户自定义字面量的机制:字面量运算符(literaloperator);如11000b–2进制字面量 C++提供了调试工具assert;C++11新增了关键字static_assert,可用于在编译阶段对断言进行测试。这样做的主要目的在于,对于在编译阶段(而不是运行阶段)实例化的模板,调试起来将更简单 C++11加强了对元编程(metaprogramming)的支持
返回顶部
语言变化
Boost库成了C++编程的重要部分,给C++11带来了深远影响;该计划的基本理念是,创建一个充当开放论坛的网站,让人发布免费的C++库 TR1(TechnicalReport1)是C++标准委员会的部分成员发起的一个项目,它是一个库扩展选集,这些扩展与C++98标准兼容,但不是必不可少的。这些扩展是下一个C++标准的候选内容;在TR1中,Boost库占了很大一部分
返回顶部