這是很久之前的筆記,整理發出來并加了一點更新。
雖然C程序能用C++編譯器編譯,但是嚴格來說,C++ 不是 C 的一個超集。《為什么說C++不是C的超集? - 知乎》 這里有網友的解答,不再贅述。
C 和 C++ 混合使用的例子
// foo.h
#ifdef __cplusplus
extern "C" {
#endif
int add(int x, int y);
#ifdef __cplusplus
}
#endif
// foo.c
int add(int x, int y) {
return x+y;
}
// main.cpp
#include "foo.h"
int main() {
add(1, 2);
return 0;
}
編譯的命令是
gcc -c foo.c
g++ main.cpp foo.o -o main
C++ 中的 C++ 11 特性
一份個人的筆記,不是完整版,僅供參考
C++11 引入了 nullptr 關鍵字,專門用來區分空指針、0。nullptr 的類型為 nullptr_t
constexpr是限定了修飾的為編譯期間可確定的常量,但是constexpr也是可以用于函數的,
constexpr int fibonacci(const int n) {
return n == 1 || n == 2 ? 1 : fibonacci(n-1)+fibonacci(n-2);
}
Clang在處理constexpr時,在編譯期間用一個C++的計算器計算constexpr的值,并且記錄計算的次數。當次數超過一定值時,這個constexpr退化為非constexpr。
- 使用 auto 進行類型推導的一個最為常見而且顯著的例子就是迭代器。
for(vector<int>::const_iterator itr = vec.cbegin(); itr != vec.cend(); ++itr)
for(auto itr = vec.cbegin(); itr != vec.cend(); ++itr)
auto不能用于函數傳參,因此下面的做法是無法通過編譯的(考慮重載的問題,我們應該使用模板),auto 還不能用于推導數組類型:int arr[10] = {0},auto a[10] = arr
int array[] = {1,2,3,4,5};
for(auto &x : array) {
std::cout << x << std::endl;
}
//& 啟用了引用, 如果沒有則對 arr 中的元素只能讀取不能修改,不加卻又修改不會報錯。
- decltype 聲明某種類型
auto x = 1;
auto y = 2;
decltype(x+y) z;
尾置返回允許我們我們在參數列表后聲明返回類型
template<T>
auto f(T a,T b) -> decltype(*a)
{
return *a;
}
- int a[3] = {1,2,3} 列表初始化
struct A {
int a;
float b;
};
struct B {
B(int _a, float _b): a(_a), b(_b) {}
private:
int a;
float b;
};
A a {1, 1.1}; // 統一的初始化語法
B b {2, 2.2};
-
std::initializer_list
,允許構造函數或其他函數像參數一樣使用初始化列表,
#include <iostream>
#include <initializer_list>
using namespace std;
int f(initializer_list<int> list)
{
int ans = 0;
for(auto i : list)
ans += i;
return ans;
}
cout<<f({1,2,3});
- C++11 開始,連續的右尖括號將變得合法,并且能夠順利通過編譯。
typedef int (*process)(void *); //
定義了一個返回類型為 int,參數為 void* 的函數指針類型,名字叫做 process
using process = int(*)(void *);
// 同上, 更加直觀
template <typename T>
using NewType = SuckType<int, T, 1>; // 合法
- 默認模板參數
template<typename T=int, typename U=int>
auto add(T x, U y) {
return x+y;
}
- 委托構造
class Base {
public:
int v1,v2;
Base() {
v1 = 1;
}
Base(int value) : Base() { //成員初始化列表 委托 Base() 構造函數
v2 = 2;
}
Base(int value) { // 委托 Base() 構造函數
Base();
v2 = 2;
}
};
- 繼承構造
class Test : public Base{
public:
test() {
using Base::Base; // 繼承構造
}
}
- 引入 override 關鍵字將顯式的告知編譯器進行重載,編譯器將檢查基函數是否存在這樣的虛函數,否則將無法通過編譯:
struct Base {
virtual void foo(int);
};
struct SubClass: Base {
virtual void foo(int) override; // 合法
virtual void foo(float) override; // 非法, 父類沒有此虛函數
};
final 則是為了防止類被繼續繼承以及終止虛函數繼續重載引入的。
struct Base {
virtual void foo() final;
};
struct SubClass1 final: Base {
}; // 合法
struct SubClass2 : SubClass1 {
}; // 非法, SubClass 已 final
struct SubClass3: Base {
void foo(); // 非法, foo 已 final
};
- 枚舉類 此處默認 unsigned int , 未指定時將默認使用 int
enum class new_enum : unsigned int {
value1,
value2,
value3 = 100,
value4 = 100
};
- 捕獲錯誤
try{
//
}catch(runtime_error e) {
cout<<e.what()<<endl;
}
來自個人 C++ 文集