C++11 是第二个真正意义上的 C++ 标准,也是 C++ 的一次重大升级。C++11 增加了很多现代编程语言的特性,比如自动类型推导、智能指针、lambda 表达式等,这使得 C++ 看起来又酷又潮,一点也不输 Java 和 C#。
#include
#include
using namespace std;
/************************************
*1.auto的应用:
*描述:自动推导变量类型(只能用于类的静态成员)
*************************************/
class A
{
public:
static int getVal()
{
return 10;
}
};
class B
{
public:
static const char* getVal()
{
return "hello";
}
};
template
auto func()
{
auto val = T::getVal();
return val;
}
void useAuto()
{
/*1.1 在迭代器中使用*/
QVector v = {2, 4, 6, 8};
//不使用auto
for(QVector::iterator it = v.begin(); it != v.end(); it++)
{
v.push_back(*it);
}
qDebug() << "not use auto v[1]:" << v[1];
//使用auto
for(auto it = v.begin(); it != v.end(); it++)
{
v.push_back(*it);
}
qDebug() << "use auto v[1]:" << v[1];
/*1.2 在泛型编程中使用*/
qDebug() << "A Val: " << func();
qDebug() << "B Val: " << func();
}
/************************************
*2.decltype的应用:
* 描述:自动推导变量类型(能用于类的非静态成员)
*************************************/
template
class C
{
public:
void setVal(T& container)
{
m_it = container.begin();
}
decltype(T().begin()) getVal()
{
return m_it;
}
private:
decltype(T().begin()) m_it; //使用typename T::iterator m_it,并不能包括所有的迭代器类型,当 T 是一个 const 容器时,会报错
};
void useDecltype()
{
/*2.1在泛型编程中使用*/
QVector v = {2, 4, 6, 8};
C> obj;
obj.setVal(v);
qDebug() << "decltype val:" << *(obj.getVal());
}
/************************************
*3.返回值后置运用于泛型编程:
* 描述:将 decltype 和 auto 结合起来完成返回值类型的推导
*************************************/
#include
using namespace std;
double foo(int a)
{
return (double)a + 0.1;
}
int foo(double b)
{
return (int)b;
}
template
auto Forward(T t) -> decltype(foo(t))
{
return foo(t);
}
void useForward()
{
qDebug() << "Forward(2):" << Forward(2);
qDebug() << "Forward(0.5):" << Forward(0.5);
}
/************************************
*4.using的应用:
* 描述:typedef无法重定义一个模板,using 的别名语法覆盖了typedef的全部功能
*************************************/
//定义变量类型
using uint_t = unsigned int;
//定义模板
template
using str_map_t = std::map;
template
using func_t = void (*)(T, T);
func_t xx_2;
/************************************
*5.类模板可以有默认的模板参数:
* 描述:typedef无法重定义一个模板,using 的别名语法覆盖了typedef的全部功能
*************************************/
template
R func(U val)
{
return val;
}
void useClassWithDefaultPara()
{
func(97); // R=int, U=int 编译器可以根据实参 97 自行推导出模板参数 U 的类型为 int,并且根据返回值 val=97 推导出 R 的类型也为 int
func(97); // R=char, U=int 手动指定了模板参数 R 的类型为 char(默认模板参数将无效),并通过实参 97 推导出了 U = int
func(97); // R=double, U=int 手动指定的 R 和 U 的类型值,因此无需编译器自行推导
}
/************************************
*6.tuple元组的应用:
* 描述:实例化的对象可以存储任意数量、任意类型的数据
*************************************/
#include
using std::tuple;
//给自定义结构体、类实现比较操作符时,
//下述代码会优先按照第一个字段n进行比较,相等的话进而判断第二个字段,最后到第三个字段,直到能够获得比较的结果为止。
struct S {
int n;
std::string s;
float d;
bool operator<(const S& rhs) const {
return std::tie(n, s, d) < std::tie(rhs.n, rhs.s, rhs.d);
}
};
void useTuple()
{
//创建一个 tuple 对象存储 10 和 'x'
std::tuple mytuple(10, 'x');
//计算 mytuple 存储元素的个数
int size = std::tuple_size::value;
//输出 mytuple 中存储的元素
qDebug() << "size:" << size << std::get<0>(mytuple) << " " << std::get<1>(mytuple);
auto bar = std::make_tuple("test", 3.1, 14);
//拆解 bar 对象,分别赋值给 mystr、mydou、myint
const char* mystr = nullptr;
double mydou;
int myint;
//使用 tie() 时,如果不想接受某个元素的值,实参可以用 std::ignore 代替
std::tie(mystr, mydou, myint) = bar;
}
/************************************
*7.统一了初始化方式:
* 描述:实例化的对象可以存储任意数量、任意类型的数据
*************************************/
class Foo
{
public:
Foo(int) {}
private:
Foo(const Foo &);
};
void useInitList()
{
Foo a3 = { 123 }; //列表初始化方式,使用了等于号,但私有的拷贝构造并不会影响到它
Foo a4 { 123 };// C++11特有
}
/************************************
*8.lambda匿名函数的应用:
* 描述:所谓匿名函数,简单地理解就是没有名称的函数,又常被称为 lambda 函数或者 lambda 表达式
* [] 空方括号表示当前 lambda 匿名函数中不导入任何外部变量
* [=] 只有一个 = 等号,表示以值传递的方式导入所有外部变量
* [&] 只有一个 & 符号,表示以引用传递的方式导入所有外部变量
* [val1,val2,...] 表示以值传递的方式导入 val1、val2 等指定的外部变量,同时多个变量之间没有先后次序
* [&val1,&val2,...] 表示以引用传递的方式导入 val1、val2等指定的外部变量,多个变量之间没有前后次序
* [val,&val2,...] 以上 2 种方式还可以混合使用,变量之间没有前后次序
* [=,&val1,...] 表示除 val1 以引用传递的方式导入外,其它外部变量都以值传递的方式导入
* [this] 表示以值传递的方式导入当前的 this 指针
*************************************/
int all_num = 0;
void useLambda()
{
/*对a 数组中的元素进行排序*/
int num[4] = {4, 2, 3, 1};
sort(num, num+4, [=](int x, int y) -> bool{ return x < y; });
for(int n : num){
qDebug() << "useLambda:" << n << " ";
}
//值传递
int num_1 = 1;
int num_2 = 2;
int num_3 = 3;
qDebug() << "lambda1:\n";
auto lambda1 = [=]{
//全局变量可以访问甚至修改
all_num = 10;
//函数体内只能使用外部变量,而无法对它们进行修改
qDebug() << num_1 << " "
<< num_2 << " "
<< num_3;
};
lambda1();
//借助 mutable 关键字, 可以在lambda2 匿名函数的基础上修改外部变量的值
auto lambda2 = [=]() mutable{
num_1 = 10;
num_2 = 20;
num_3 = 30;
//函数体内只能使用外部变量,而无法对它们进行修改
qDebug() << num_1 << " "
<< num_2 << " "
<< num_3;
};
lambda2();
//引用传递
auto lambda3 = [&]{
all_num = 100;
num_1 = 10;
num_2 = 20;
num_3 = 30;
qDebug() << num_1 << " "
<< num_2 << " "
<< num_3;
};
lambda3();
}
/************************************
*9.非受限联合体(union):
* 描述:实例化的对象可以存储任意数量、任意类型的数据
*************************************/
//C++11 删除了联合体不允许拥有静态成员的限制
/*
union U {
static int func() {
int n = 3;
return n;
}
};*/
/************************************
*10.for循环的应用:
* 描述:for (declaration : expression){
//循环体}
*************************************/
void useFor()
{
QVector v5 = {2, 4, 6, 8};
//读写访问
for(auto& i : v5)
{
i++;
}
//只读访问
for(int i : v5)
{
qDebug() << "i:" << i;
}
}
/************************************
*11.constexpr的应用:
* 描述:编译阶段即可计算出结果
*************************************/
//修饰函数, 只能一条语句
constexpr int display(int x) {
//可以添加 using 执行、typedef 语句以及 static_assert 断言
return 1 + 2 + x;
}
void useConstexpr()
{
//修饰变量
constexpr int length = 6;
int url[length] = {1, 2, 3};
qDebug() << "useConstexpr: url[1]:" << url[1];
qDebug() << "useConstexpr: display(5):" << display(5);
}
/************************************
*12.右值引用:
* 描述:指的是以引用传递(而非值传递)的方式使用 C++ 右值
*************************************/
void useRightValue()
{
//左值引用
int num = 10;
int &b = num; //正确
//int &c = 10; //错误
//常量左值引用
int num2 = 10;
const int &b2 = num;
const int &c2 = 10;
//右值引用
int num3 = 10;
//int && a = num; //右值引用不能初始化为左值
int && a = 10;
a = 100;
qDebug() << "useRightValue: a:" << a;
}
/************************************
*13.move()函数的应用:
* 描述:该函数并不能移动任何数据,它的功能很简单,就是将某个左值强制转化为右值
*************************************/
class demo {
public:
demo(int num):num(num){}
int get_num()&&{ //仅供右值调用
return this->num;
}
private:
int num;
};
void useMove()
{
demo a(10);
//qDebug() << a.get_num() << endl; // 错误
qDebug() << move(a).get_num() << endl; // 正确 左值被强制为右值
}
/************************************
*14.nullptr的应用:
* 描述:相比 NULL 和 0,使用 nullptr 初始化空指针可以令我们编写的程序更加健壮
*************************************/
void isnull(void *c){
cout << "void*c" << endl;
}
void isnull(int n){
cout << "int n" << endl;
}
void useNullptr()
{
isnull(0);
isnull(NULL);
isnull(nullptr);
}
/************************************
*14.智能指针的应用:
* 描述:智能指针主要分为QSharedPointer、shared_ptr(共享的智能指针)、QScopedPointer、unique_ptr(独占的智能指针)和QWeakPointer、weak_ptr(弱引用的智能指针)三种,shared_ptr是使用最多的一种
* 智能指针可以在适当时机自动释放分配的内存。也就是说,使用智能指针可以很好地避免“忘记释放内存而导致内存泄漏”问题出现
* 智能指针的核心实现技术是引用计数,每使用它一次,内部引用计数加1,每析构一次内部的引用计数减1,减为0时,删除所指向的堆内存
*************************************/
#include
#include
class OnePiece {
public:
OnePiece() {
qDebug() << QString("OP");
}
~OnePiece() {
qDebug() << QString("~OP");
}
public:
void print() {
qDebug() << QString("OP Print ");
}
};
class Nika : public QObject {
public:
Nika() {
qDebug() << "Nika()";
}
~Nika() {
qDebug() << "~Nika()";
}
public:
void print() {
qDebug() << "Nika Print";
}
};
void useSmartPointer()
{
//QSharedPointer 与 QWeakPointer(为了监视QSharedPointer)
QSharedPointer op1 = QSharedPointer(new OnePiece); //引用计数为1
QSharedPointer op2(op1); //引用计数为2
QSharedPointer op3 = op1; //引用计数为3
op3->print();
// 弱引用
QWeakPointer op4 = op1; //引用计数为3
// 弱引用转为强引用
QSharedPointer op5 = op4.toStrongRef(); //引用计数为4
QSharedPointer op6 = op4.lock(); //引用计数为5
op6->print();
QSharedPointer op = QSharedPointer(new OnePiece); //引用计数为1
OnePiece *op7 = op.data();
op7->print();
OnePiece *op8 = op.get();
op8->print();
QSharedPointer op9 = QSharedPointer(new OnePiece); //引用计数为1
QSharedPointer op10(op9); //引用计数为2
op10.clear(); //引用计数为1
if (op10.isNull()) {
qDebug() << "op10 is null";
}
//独享指针 没有拷贝构造和赋值构造 独占内存
QScopedPointer op11(new OnePiece);
op11->print();
//QPointer 只能使用于继承自QObject的类
QPointer nika1(new Nika);
QPointer nika2 = nika1;
if (!nika1.isNull()) {
nika1->print();
}
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
//auto的应用
useAuto();
//decltype的应用
useDecltype();
//返回值后置的应用
useForward();
//类模板可以有默认的模板参数
useClassWithDefaultPara();
//Tuple元组的应用
useTuple();
//列表初始化方式
useInitList();
//lambda匿名函数的应用
useLambda();
//for循环的应用
useFor();
//constexpr的应用
useConstexpr();
//右值引用
useRightValue();
//nullptr的应用
useNullptr();
//智能指针的应用
useSmartPointer();
return a.exec();
}

参考:http://c.biancheng.net/cplus/11/