1、auto 关键字的新意义
auto x = 5; // OK: x是int类型
auto pi = new auto(1); // OK: pi被推导为int*
const auto *v = &x, u = 6; // OK: v是const int*类型,u是const int类型
static auto y = 0.0; // OK: y是double类型
auto int r; // error: auto不再表示存储类型指示符
auto s; // error: auto无法推导出s的类型
在上面的代码示例中:
字面量 5 是一个 const int 类型,变量 x 将被推导为 int 类型(const被丢弃,后面说明),并被初始化为 5。
pi 的推导说明 auto 还可以用于 new 操作符。在例子中,new 操作符后面的 auto(1) 被推导为 int(1),因此 pi 的类型是 int*。
接着,由 &x 的类型为 int*,推导出 const auto* 中的 auto 应该是 int,于是 v 被推导为 const int*,而 u 则被推导为 const int。
最后 y、r、s 的推导过程比较简单,就不展开讲解了。读者可自行在支持 C++11 的编译器上实验。
auto的限制
在 Foo 中,auto 仅能用于推导 static const 的整型或者枚举成员(因为其他静态类型在 C++ 标准中无法就地初始化),虽然 C++11 中可以接受非静态成员变量的就地初始化,但却不支持 auto 类型非静态成员变量的初始化。
在 main 函数中,auto 定义的数组 rr 和 Barbb 都是无法通过编译的。
注意 main 函数中的 aa 不会被推导为 int[10],而是被推导为 int*。这个结果可以通过 auto 与函数模板参数自动推导的对比来理解。
void func(auto a = 1) {} // error: auto不能用于函数参数
struct Foo
{
auto var1_ = 0; // error: auto不能用于非静态成员变量
static const auto var2_ = 0; // OK: var2_ -> static const int
};
template <typename T>
struct Bar {};
int main(void)
{
int arr[10] = {0};
auto aa = arr; // OK: aa -> int *
auto rr[10] = arr; // error: auto无法定义数组
Bar<int> bar;
Bar<auto> bb = bar; // error: auto无法推导出模板参数
return 0;
}
C++ override 关键字用法
如果派生类在虚函数声明时使用了override描述符,那么该函数必须重载其基类中的同名函数,否则代码将无法通过编译。
C++11 Tasks 线程与任务的区别
线程需要头文件,而task需要头文件。
线程的参与者是创建主线程和子线程,task的参与者是promise和future。
线程操作的共享变量res是通过子线程传递给父线程方式计算的结果。
然而promise 和 future使用一个公共的数据通道,std::async创建的这个数据通道,使用future变量fut.get获取计算的结果。
使用线程你必须使用锁来保护共享变量。
但是promise 和 future不会有机会出现竞争条件。
主线程等待子线程结束需要子线程调用join函数;然而fut.get 调用直接阻塞。
如果子线程中存在异常,则子线程和创建者线程终止,最终整个程序gg。
然而promise可以为future返回一个异常,future必须处理这个异常。
子线程只能通过值向主线程传递数据,但是promise能传递值,异常,消息通知等给future。
在C++11中,我们可以在for循环填加冒号 : 来简化这一过程:
//随机定义的数组
int array[10] = { 54, 23, 78, 9, 15, 18, 63, 33, 87, 66 };
for (auto a : array) {
cout << a << " "; //输出:54 23 78 9 15 18 63 33 87 66
}
for (auto& task : tasks_) {
// 监控任务每次循环的时间
if (task->isSlow()) {
task->PrintStatus();
task->ClearMax();
}
// 监控任务是否异常,若异常重启任务
if (task->isAbnormal()) {
AINFO_F("[PeriodicTaskManager] Task < %s > is anbormal. Restart the task automatically \n",
task->getName().c_str());
task->Stop();
task->Start();
}
}
C++11枚举类——enum class
众所周知在C++中,变量名字仅仅在一个作用域内生效,出了大括号作用域,那么变量名就不再生效了。但是传统C++的enum却特殊,只要有作用域包含这个枚举类型,那么在这个作用域内这个枚举的变量名就生效了。即枚举量的名字泄露到了包含这个枚举类型的作用域内。在这个作用域内就不能有其他实体取相同的名字。所以在C++98中这个称之为不限范围的枚举型别
enum Color{black,white,red}; //black、white、red作用域和color作用域相同
auto white = false; //错误,white已经被声明过了
类优势——降低命名空间污染
使用枚举类的第一个优势就是为了解决传统枚举中作用域泄露的问题。在其他地方使用枚举中的变量就要声明命名空间。
enum class Color{black,white,red}; //black、white、red作用域仅在大括号内生效
auto white = false; //正确,这个white并不是Color中的white
Color c = white; //错误,在作用域范围内没有white这个枚举量
Color c = Color::white; //正确
auto c = Color::white; //正确