7.1 指针空值 nullptr
在C++中一般一个指针声明都是char* p = NULL;
表示一个指针处于初始化状态,NULL一般是一个宏定义,定义如下:
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif
此时我们如下使用就会出问题,我们想要通过func(NULL)
调用一个指针类型的重载,而MSVC编译器将会调用int
入参类型的fun
函数重载这显然不是我们想要的。
void fun(char *c)
{
cout << "fun char *" << endl;
}
void fun(int i)
{
cout << "fun int " << endl;
}
//打印:fun int
fun(NULL);
在C++11中nullptr
则是一个“指针空值类型”,在C++11中指针空值类型被命名为nullptr_t
定义为,事实上,我们可以在cstddef中(或者其包含的头文件中找到如下定义):
typedef decltype(nullptr) nullptr_t;
比如在模板推导时,编译器一般都可以指出nullptr
为nullptr_t
,另外在模板类型为T*时,我们传入nullptr
则是编译失败,需要手动增加显式类型转换。
template<typename T> void g(T*t) {
cout << typeid(T).name() << endl;
}
template<typename T> void f(T t) {
cout << typeid(T).name() << endl;
}
g((float*)nullptr);
//g(nullptr); //error
f(nullptr);
//打印
//float
//std::nullptr_t
7.2 默认函数的控制
C++11中提供了default
和delete
来修饰默认构造、拷贝等函数。
简单的使用如下:
class ConvType
{
public:
ConvType(int i) {};
ConvType() = default;
ConvType(char c) = delete;
};
void func(ConvType ct) {}
//使用如下
func(1); //隐式转换
func(ConvType()); //默认构造函数
func('c'); //编译失败
当然如果我们想要一个对象,不能使用堆来构造对象,可以删除自定义类型的operator new
操作符即可,示例如下:
class NoHeapAlloc
{
public:
void * operator new (std::size_t) = delete;
};
NoHeapAlloc nha;
NoHeapAlloc *pnha = new NoHeapAlloc; //编译失败
7.3 lambda函数
lambda在C++11中的形式如下:
auto sum = [](int x,int y) -> int{ return x + y; };
语法定义如下:
[capture] (parameters) mutable -> return-type {statement}
- [captrue]:捕捉列表,总是出现在lambda函数开始处。
捕获列表描述:- [var]传值捕获var。
- [=]捕捉父作用域所有变量,包括this。
- [&var]引用传递变量var。
- [&]引用捕捉父作用域所有变量,包括this。
- [this]值传递方式捕捉this指针。
- (parameters) :参数列表,没有参数可以省略。
- mutable:默认lambda是const类型函数,mutable可以取消常量性。
- -> return-type:返回类型,用追踪返回类型形式声明函数返回类型。
- {statement}:与普通函数一致。
lambda对于C++11中最大的贡献应该是对于STL库的改变了,我们会发现使用STL算法更容易了。
比如for_each
的原型:
template<class InputIt, class UnaryFunction>
constexpr UnaryFunction for_each(InputIt first, InputIt last, UnaryFunction f)
{
for (; first != last; ++first) {
f(*first);
}
return f; // implicit move since C++11
}
我们结合lambda可以如下使用:
std::vector<int> arr{6,5,3,21,1,3,54,3,6};
//打印偶数
for_each(arr.begin(), arr.end(), [&arr](int val)
{
if (val % 2 == 0)
{
cout << val << " ";
}
});
7.4 本章小结
本章主要讲解:nullptr、default、delete、lambda。