追踪返回类型:
就是返回类型后置,
可用于函数模块,也被广泛用于转发函数(如:可以实现参数和返回类型不同时的转发)中,还可用在函数指针、函数引用中;
类型安全:
宏的弱点:在于其定义的只是在预处理阶段的名字
枚举类型的缺点:全局可见,对个枚举类型内的枚举值可能会发生冲突,导致编译失败;
C++98枚举缺点:
非强类型作用域,允许隐式转换为整型,占用存储空间及符号性不确定
C++11:枚举类,又称强类型枚举,在enum后面加上class,即可,还可以指定出wchar_t以外的任何整型;
enum class Type: char { General, Light, Medium, Heavy };
优点:强作用域,转换限制,可以指定底层类型;
智能指针
shared_ptr参与指向内存的引用计数
weak_ptr不参与,可以通过成员lock指向对象内存,但不拥有该内存。
unique_prt代替了以前使用auto_ptr的。而shared_ptr以及weak_ptr则可用在用户需要引用计数的地方。
智能指针能帮助用户进行有效的堆内存管理,但需要显示声明,而完全不用考虑回收指针类型的内存管理方案更讨人喜欢。
垃圾回收分类
垃圾是指:把之前使用过,现在不再使用或没有任何指针再指向的内存空间;
垃圾回收机制是指:将这些“垃圾”收集起来以便再次利用的机制;
1.基于引用计数的垃圾回收器:
优点副作用较小(不会有对系统缓存或交换空间造成的冲击),缺点容易形成“环形引用”问题,由于计数带来的额外开销并不小,所以在实用上有一定的限制
2.基于跟踪处理的垃圾回收器:
与1相比,被更广泛的应用。基本方法是产生跟踪对象的关系图,然后进行垃圾回收。
三种算法:标记-清除;标记-整理;标记-拷贝;
C++与垃圾回收:
由于通过引用计数不能解决如“环形引用”的问题,如因多线程程序等而引入的内存管理上的困难,程序员可能需要垃圾回收,如第三方C++垃圾回收库-Boehm,但可移植性较差。
C++11中的“最小垃圾回收支持”,通过语言的约束来保证安全的垃圾回收机制。
要保证安全的垃圾回收,首先必须知道C/C++语言中什么样的行为可能导致垃圾回收中出现的“不安全”状况。简单来说,不安去源自于C/C++语言对指针的“放纵”,即允许过分灵活的使用。当发生指针进行自加或自减操作,或指针被异或覆盖再恢复时,会触发垃圾回收。
定义了“安全”(或称安全派发)指针的操作(即安全派发操作):
1.在解引用基础上的引用,如&*p
2.定义明确的指针操作:如:p+1
3.定义明确的指针转换:如:static_cast<void*>(p)
4.指针和整型之间的reinterpret_cast,如reinterpret_cast<intptr_t>(p)
intptr_t是C++11中一个可选择实现的类型,其长度等于平台上指针的长度(通过decltype声明)
异或不是安全派发操作
pointer_safety get_pointer_safety() noexcept # 查询确认编译器是否支持最小垃圾回收
声明该指针所指的内存为“可到达”的:
void declare_reachable(void* p);
template<class T> T *undeclare_reachable(T *p) noexcept;
declare_reachable和undeclare_reachable只是确立了一个代码范围,即两者之间的代码运行中,指针对象不会被垃圾回收器回收。
在一大片连续的堆内存上进行指针式操作,为了让垃圾回收器不关心该区域,可以用如下代码:
void declare_no_pointers(char* p, size_t n) noexcept;
void undelcare_no_pointers(char *p, size_t n) noexcept;
指定的是从p开始的连续n的内存。
不向后兼容,对于老的代码我们需要限制指针的使用或使用上述两种方式,让一些不安全的指针使用免于垃圾回收器的检查。
仅限于在new操作符分配的内存,而malloc分配的内存则被认为总是可达的。因此,有malloc等较老代码的堆内存还是必须由程序员自己控制。
显示的delete使用与垃圾回收并不会形成冲突,可以保证代码最大可能性的向前兼容(面向未来)。
理想情况下,程序员应该总是在栈上分配变量,这样变量能够有效地自动释放。
std::tuple<int, char, std::string> a(std::make_tuple(1,'H', "Hello")); int n = std::get<0>(a); char c = std::get<1>(a); std::string d = std::get<2>(a);
变长模板函数远强于变长函数,因为变长模板函数不会丢失参数的类型信息,示例代码如下:
void Printf(const char *s) { while(*s) { if (*s == '%' && *++s != '%') throw std::runtime_error("invalid format string: missing arguments"); std::cout << *s++; } } template<typename T, typename... Args> void Printf(const char* s, T value, Args... args) { while(*s) { if (*s == '%' && *++s != '%') { std::cout << value; return Printf(++s, args...); } std::cout << *s++; } throw std::runtime_error("extra arguments provided to Printf"); } Printf("hello %s ", std::string("world").c_str());