版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_34536551/article/details/89173348
目录
nullptr 和 std::nullptr_t、以及与NULL 有何不同
初始化列表、窄化转换、使用 std::initializer_list (15P)
左值引用 、右值引用 和 标准库 Move 函数 (19P)
char16_t 和 char32_t、 long long 和 unsigned long long 、 std::nullptr_t 新的内存类型 (33P)
非类型模板参数、模板参数默认值、关键字Typename、成员模板、类模板嵌套 (33P)
nullptr 和 std::nullptr_t、以及与NULL 有何不同
- NULL 是一个预处理变量,在头文件 cstdlib 中定义,可以为指针赋值,它的值本身就是0.
- nullptr 是一种特殊类型的字符值,它可以转换为任意的其它指针类型,是不会被转换成任何其它整型的。该 关键字的类型为std :: nullptr_t,在<cstddef>中定义。
- 如果用 字符值0初始化指针,表示将该指针初始化为空指针
用一个NULL 初始化指针时,预处理器会自动地将它替换为实际值。因此用NULL 初始化指针 和用0初始化指针是一样的。
auto 类型
int main()
{
auto i; // 以auto声明的变量,其变量的类型会初动推导出来, 因此该变量必须被初始化
static auto vat = 0.19; // 可以在 auto 前加 其它限定符
vector<string> v;
auto pos = v.begin(); // pos has type vector<string>::iterator
system("pause");
return 0;
}
初始化列表、窄化转换、使用 std::initializer_list (15P)
使用 “ { }” 初始化话会强制执行所谓的值初始化,这意味着即使是内置类型的局部变量(没有被初始化),也会被0初始化(如果是指针,则为nullptr):
int i; // i has undefined value
int j{}; // j is initialized by 0
int* p; // p has undefined value
int* q{}; // q is initialized by nullptr
void print(std::initializer_list<int> vals)
{// initializer_list 中的元素永远是常量,我们不可以修改它的值
for (auto p = vals.begin(); p != vals.end(); ++p)
{ // process a list of values
std::cout << *p << "\n";
}
}
int main()
{
print({ 12,3,5,7,11,13,17 }); // pass a list of values to print(),而且传递的序列必须在 { } 号内
system("pause");
return 0;
}
class P
{
public:
P(int i, int c)
{
cout << i << " " << c << endl << endl;
}
P(std::initializer_list<int> il)
{
for (auto p = il.begin(); p != il.end(); ++p)
{
std::cout << *p << "\n";
}
cout << endl;
}
};
int main()
{
// 我们只能使用 ( )或 { } 初始化带有 explicit的构造函数,不能使用 = 初始化,但可以显式使用 = 初始化
P p(77, 5); // calls P::P(int,int)
P q{ 77,5 }; // calls P::P(initializer_list)
P r{ 77,5,42 }; // calls P::P(initializer_list)
P s = { 77,5 }; // calls P::P(initializer_list)
system("pause");
return 0;
}
class P
{
public:
P(int a, int b)
{
cout << " 调用的是带两个参数的构造函数!" << endl;
}
explicit P(int a, int b, int c) {
cout << "调用的是 explicit 带有三个参数的构造函数!" << endl;
}
};
int main()
{
// 我们只能使用 ( )或 { } 初始化带有 explicit的构造函数,不能使用 = 初始化,但可以显式使用 = 初始化
P x(77, 5); // OK,调用的是 p( int,int)
P y{ 77,5 }; // OK,调用的是 p( int,int)
P z{ 77,5,42 }; // OK,调用的是 explicit (int,int,int)
P v = { 77,5 }; // OK (implicit type conversion allowed).调用的是 p( int,int)
P w = { 77,5,42 }; // ERROR due to explicit (不允许隐式类型转换 ),复制列表初始化不能使用标记为“显式”的构造函数
system("pause");
return 0;
}
class P
{
public:
P(int a, int b)
{
cout << " 调用的是带两个参数的构造函数!" << endl;
}
explicit P(int a, int b, int c) {
cout << "调用的是 explicit 带有三个参数的构造函数!" << endl;
}
};
void fp(const P&)
{
}
int main()
{
fp({ 47,11 }); // OK, implicit conversion of {47,11} into P
fp({ 47,11,3 }); // ERROR due to explicit
fp(P{ 47,11 }); // OK, explicit conversion of {47,11} into P
fp(P{ 47,11,3 }); // OK, explicit conversion of {47,11,3} into P
system("pause");
return 0;
}
如果一个 explicit 构造函数 接受一个 初始化化列表,那么该构造函数不具有隐式转换的能力。
范围 for循环 (17P)
左值引用 、右值引用 和 标准库 Move 函数 (19P)
可变参数模板、模板别名 ( 27P)
Lambda 表达式 (28P)
int main()
{
int x = 0;
int y = 42;
auto qqq = [x, &y] {
std::cout << "x: " << x << std::endl;
std::cout << "y: " << y << std::endl;
++y; // OK
};
x = y = 77;
qqq();
qqq();
std::cout << "final y: " << y << std::endl;
std::cout << "final x: " << x<< std::endl;
system("pause");
return 0;
}
输出结果为:
x: 0
y: 77
x: 0
y: 78
final y: 79
final x: 77
y 以 通过 引用传递, 在 lambda 函数体中如果修改了其引用的对象的值,那么该值的变化也会影响到其引用的对象的值。
int main()
{
int id = 0;
auto f = [id]() mutable {
std::cout << "id: " << id << std::endl;
++id; // OK
};
id = 42;
f();
f();
f();
std::cout << id << std::endl;
system("pause");
return 0;
}
输出结果为:
id: 0
id: 1
id: 2
42
id 是通过值传递的,虽然我们显式使用 mutable 关键字指出可以修改被捕获变量的值,但是被修改的值并不会影响到 其外部的对象。
std::function<int(int, int)> returnLambda()
{
return [](int x, int y) {
return x * y;
};
}
int main()
{
auto lf = returnLambda();
std::cout << lf(6, 7) << std::endl;
system("pause");
return 0;
}
decltype 关键字 ( 32P)
std::map<std::string,float> coll;
decltype(coll)::value_type elem; // elem 的类型是一个 pair< const string ,float >