Language Standards Supported by GCC
GCC 4.7及之后的版本才支持C11
- C89=C90:gcc选项是:-ansi, -std=c90 or -std=iso9899:1990;
- 带了GNU扩展的:-std=gnu90
- C94=C95:gcc选项:-std=iso9899:199409
- C99:gcc选项:-std=c99 or -std=iso9899:1999
- 未完成C99标准之前,叫做C9X
- 带了GNU扩展的:-std=gnu99
- C11:gcc选项是-std=c11 or -std=iso9899:2011
- 未完成C11标准之前,叫做C1X
- 带了GNU扩展的:-std=gnu11
注意:GCC/G++默认的-std(即C++语言标准)不是C++11,而是C++98,所以要支持C++11的新特性,需要显式地开启,即添加-std=c++11选项。
C++11
C++的创始人:Bjarne Stroustrup
C++11(即ISO/IEC 14882:2011),是目前的C++编程语言的最新正式标准。它取代了第二版标准(第一版公开于1998年,第二版于2003年更新,分别通称C++98以及C++03,两者差异很小)。新的标准包含核心语言的新机能,而且扩展C++标准程序库。C++11新标准由C++标准委员会于2011年8月12日公布,并于2011年9月出版。此次标准为C++98发布后13年来第一次重大修正。
头文件
C++的头文件很乱,常见的有以下3种样式:
#include <xxxx>
#include <yyy.h>
#include <czzz>
其中,
- C++标准库的头文件
- 应该这样引用:
#include <xxxx>
,如iostream; - 尽管仍旧支持iostream.h的方式,但这种做法已经被摒弃,在官方标准中被剔除;
- 应该这样引用:
- C标准库的头文件
- 这样引用:
#include <xxx.h>
; - 也能这样引用:
#include <cxxx>
,其功能与xxx.h
一致,但被纳入了std namespace;
- 这样引用:
- 非C/C++标准库的头文件
- 比如OS或POSIX的头文件,比如pthread.h和unistd.h;
- 只能按
#include <xxx.h>
的方式;
特别注意一下string头文件:
C++要兼容C的标准库,而C的标准库里碰巧也已经有一个名字叫做“string.h”的头文件,包含一些常用的C字符串处理函数,比如strcpy、strcmp;
这个string.h头文件跟C++的std::string类半点关系也没有,所以<string>
并非<string.h>
的“升级版本”,他们是毫无关系的两个头文件;
<string.h>
是旧的C 头文件,对应的是基于char*的字符串处理函数;
<cstring>
是对应于旧C 头文件的std 版本;
<string>
是包装了std 的C++头文件,对应的是新的string类;
智能指针
std::shared_ptr
- 普通指针到智能指针的转换
int* iPtr = new int(42);
shared_ptr<int> p(iPtr);
- 智能指针到普通指针的转换
int* pI = p.get();
在C++11中,极力推崇完全替代原生指针。而这里面,原生指针使用到了static_cast,dynamic_cast, const_cast的操作,需要用static_pointer_cast, dynamic_pointer_cast, const_pointer_cast对应操作,而并非使用原来的dynamic_cast等。
Android strong pointer
源码:
android/system/core/libutils/RefBase.cpp
android/system/core/libutils/include/utils/StrongPointer.h
注意:所有使用sp指针的类都必须继承RefBase类(虚继承);
sp类是模板类,通过引用计数的方式管理对象的生命周期,实现对象的自动回收;
示例代码:
class T : public virtual RefBase {
public:
void a() {}
// ...
};
sp<T> t = new T();
t->a(); // call T's member function
T* pt = t.get(); // call sp's function
上述示例代码展示了调用模板类成员函数和T类成员函数的差异!
sp vs std::shared_ptr
In the Android implementation of strong pointer, any strong-pointer based object must inherit refbase i.e.
sp<TheClass> theObj // TheClass must inherit from class RefBase
This requirement can be seen in the code for one of sp
's methods:
template<typename T> sp<T>& sp<T>::operator =(T* other) {
if (other != NULL) {
other->incStrong(this);
}
if (mPtr != NULL) {
mPtr->decStrong(this);
}
mPtr = other;
return *this;
}
In order for call to incStrong
or decStrong
to not fail . . . other
and mPtr
must have inherited RefBase
QUESTION
Why is sp
implemented such that the obj that it’s managing is required to be a child of RefBase
? There’s not even a way to enforce this requirement at compile-time or even runtime. (Well maybe if(type()...
)
ANSWER
It saves a memory allocation. When you write:
std::shared_ptr<Foo> pFoo{new Foo(bar)};
pFoo
actually has a pointer to a shared data structure (allocated on the heap), which has the reference counters, and the pointer to the actual Foo object. By making objects be derived from RefBase
, you can embed the reference counts in the object itself (saving the additional memory allocation).
Interestingly, with C++11 onwards, you can avoid the additional memory allocation by using std::make_shared<Foo>
which will do a single memory allocation and construct the shared data structure and the Foo object in it.
The fact there is no compile time checking of the derivation from RefBase
is carelessness. m_ptr
should have been declared as RefBase *m_ptr
, and then operator *
(etc) should have done a static_cast to T*
. In fact, I would probably have made sp<T>
inherit from sp_base
which had the comparison operators as public, and the other functions as protected.
Edit
On second thoughts, there is quite a bit of compile time checking. If T
doesn’t have an incStrong
member, the compilation will fail, and it almost certainly won’t unless it derives from RefBase
. I still think converting a T*
to a RefBase*
would have been a better check, but the one that is there is probably good enough.
Tips
- sleep 1秒钟
#include <thread>
#include <chrono>
std::this_thread::sleep_for (std::chrono::seconds(1));
-
线程
C++11提供了std::thread类,其实就是对pthread的封装;而且在编译时,需要链接pthread库; -
其他