c++11 你需要知道这些就够了
https://blog.csdn.net/tangliguantou/article/details/50549751
c++11新特性
舉著火把尋找電燈
今天我就權當拋磚引玉,如有不解大家一起探討。有部分內容是引用自互聯網上的內容,如有問題請聯系我。
T&& 右值引用 std::move
右值引用出現之前我們只能用const引用來關聯臨時對象(右值)所以我們不能修臨時對象的內容,右值引用的出現就讓我們可以取得臨時對象的控制權,終于可以修改臨時對象了!
int main() {int i = 42;int &r = i; // ok: r refers to iint &&rr = i; // error: cannot bind an rvalue reference to an lvalueint &r2 = i * 42; // error: i * 42 is an rvalueconst int &r3 = i * 42; // ok: we can bind a reference to const to an rvalueint &&rr2 = i * 42; int &&rr3 = rr2; // error: the expression rr2 is an lvalue!return 0; }即凡是可以 vartype varname; 這樣定義出來的變量(variable)其自身都是左值。
std::move相關。 右值引用因為綁定對象即將被銷毀,意味著沒有人會繼續訪問他們,所以就可以把他們(的資源)steal(偷)過來。 雖然不能將右值引用綁在左值上,但通過利用utility頭文件新增的函數模板move,它返回傳入對象的右值引用,可以達到 steal的效果。
int &&rr3 = std::move(rr2); // ok
再提醒:一旦使用了move,編譯器就默認傳入對象已經不打算使用了,是可以被銷毀的,move之后該對象的值已經不確定,不要再訪問。還有由于對象偷取與復制的差別巨大,不注意會產生非常難定位的bug,所以所有使用move的地方一定要使用全稱std::move,給大家以提醒。(其實c++11在algorithm頭文件也新增了一個move,參數與意義都與此截然不同)。
#include <iostream> using namespace std;class HugeMem{public:HugeMem(int size): sz(size > 0 ? size : 1) {c = new int[sz];}~HugeMem() { cout<<"HugeMem 析構\n";delete [] c; }HugeMem(HugeMem && hm): sz(hm.sz), c(hm.c) {cout<<"HugeMem move 構造\n";hm.c = nullptr;}int * c;int sz; }; class Moveable{public:Moveable():i(new int(3)), h(1024) {}~Moveable() { cout<<"Moveable 析構\n";delete i; }Moveable(Moveable && m):i(m.i), h(move(m.h)) { // 強制轉為右值,以調用移動構造函數m.i = nullptr;}int* i;HugeMem h; };Moveable GetTemp() {//Moveable tmp = Moveable();Moveable tmp;cout << hex << "Huge Mem from " << __func__<< " @" << tmp.h.c << endl; // Huge Mem from GetTemp @0x603030return tmp; }int main() {Moveable a(GetTemp());cout << hex << "Huge Mem from " << __func__<< " @" << a.h.c << endl; // Huge Mem from main @0x603030 }早在C++11之前編譯器就把優化幾乎做到了極致——局部變量返回到函數外部并賦值給外部變量這個過程基本上不存在任何多余的臨時變量構造和析構,這比move機制更加高效。顯式指定move以后,return std::move(localvar)這里會強行從localvar移動構造一個臨時變量temp,然后return temp(temp這里會有RVO優化)。
auto for循環
需要注意的是,auto不能用來聲明函數的返回值。但如果函數有一個尾隨的返回類型時,auto是可以出現在函數聲明中返回值位置。這種情況下,auto并不是告訴編譯器去推斷返回類型,而是指引編譯器去函數的末端尋找返回值類型。在下面這個例子中,函數的返回值類型就是operator+操作符作用在T1、T2類型變量上的返回值類型。
template <typename T1, typename T2> auto compose(T1 t1, T2 t2) -> **decltype**(t1 + t2) {return t1+t2; } auto v = compose(2, 3.14); // v's type is doubleauto與for配合使用
std::map<std::string, std::vector<int>> map; std::vector<int> v; v.push_back(1); v.push_back(2); v.push_back(3); map["one"] = v;for(const auto& kvp : map) {std::cout << kvp.first << std::endl;for(auto v : kvp.second){std::cout << v << std::endl;} }int arr[] = {1,2,3,4,5}; for(int& e : arr) {e = e*e; }std::lambda
“Lambda 表達式”(lambda expression)是一個匿名函數,Lambda表達式基于數學中的λ演算得名,直接對應于其中的lambda抽象(lambda abstraction),是一個匿名函數,即沒有函數名的函數。
C++11 的 lambda 表達式規范如下:
[ capture ] ( params ) mutable exception attribute -> ret { body } (1) [ capture ] ( params ) -> ret { body } (2) [ capture ] ( params ) { body } (3) [ capture ] { body } (4) 其中
(1) 是完整的 lambda 表達式形式, (2) const 類型的 lambda 表達式,該類型的表達式不能改捕獲("capture")列表中的值。 (3)省略了返回值類型的 lambda 表達式,但是該 lambda 表達式的返回類型可以按照下列規則推演出來: 如果 lambda 代碼塊中包含了 return 語句,則該 lambda 表達式的返回類型由 return 語句的返回類型確定。 如果沒有 return 語句,則類似 void f(...) 函數。 省略了參數列表,類似于無參函數 f()。
[] // 不引用外部變量 [x, &y] // x引用方式 ,y 傳值 [&] // 任何使用的外部變量都是引用方式。 [=] // 任何被使用到的外部都是傳值方式。 [&, x] // 除x傳值以外其他的都以引用方式。 [=, &z] // 除z引用以外其他的都是以傳值方式使用。
int main() {std::vector<int> c { 1,2,3,4,5,6,7 };int x = 5;c.erase(std::remove_if(c.begin(), c.end(), [x](int n) { return n < x; } ), c.end());std::cout << "c: ";for (auto i: c) {std::cout << i << ' ';}std::cout << '\n';// 可以用auto 接收一個lambda 表達式。auto func1 = [](int i) { return i+4; };std::cout << "func1: " << func1(6) << '\n'; // std::function 也可以接收lambda 表達式。std::function<int(int)> func2 = [](int i) { return i+4; };std::cout << "func2: " << func2(6) << '\n'; std::function<int()> func3 = [x]{return x;};std::cout << "func3: " << func3() << '\n';std::vector<int> someList = {1,2,3}; //這里是c++11int total = 0;double sum = 0.0f;std::for_each(someList.begin(), someList.end(), [&total](int x) { total += x; });std::cout << total << '\n';std::for_each(someList.begin(), someList.end(), [&](int x){ total += x; sum += x;});std::cout << total << '\n';std::cout << sum << '\n';//再寫一種簡單的lambda[](){std::cout<<"就地展開的lambda\n";}();}bind
std::bind是STL實現函數組合概念的重要手段,std::bind綁定普通函數(函數指針)、lambda表達式、成員函數、成員變量、模板函數等
#include <iostream> #include <functional>void f(int n1, int n2, int n3, const int& n4, int n5) {std::cout << n1 << ' ' << n2 << ' ' << n3 << ' ' << n4 << ' ' << n5 << '\n'; }int g(int n1) {return n1; }struct Foo {void print_sum(int n1, int n2){std::cout << n1+n2 << '\n';}static void static_func(std::function<int(int)> f,int n){std::cout<<"call static_func\n";std::cout<<"f(n):\t"<<f(n)<<"\n";}int data = 10; //c++11 支持聲明是就初始化值 };int main() {using namespace std::placeholders;// std::cref(n) 表示要把n以引用的方式傳入 int n = 7;auto f1 = std::bind(f, _2, _1, 42, std::cref(n), n);n = 10;f1(1, 2, 1001); // 1 is bound by _1, 2 is bound by _2, 1001 is unused// 綁定一個子表達式,用_3替換了 其他位置的變量// std::bind(g, _3) 在這里已經表示intauto f2 = std::bind(f, _4, std::bind(g, _4), _4, 4, 5);f2(10, 11, 12 ,13);// 綁定成員函數Foo foo;auto f3 = std::bind(&Foo::print_sum, foo, 95, _1);f3(5);// 綁定成員變量auto f4 = std::bind(&Foo::data, _1);std::cout << f4(foo) << '\n';// 綁定靜態成員函數auto f5 = std::bind(&Foo::static_func,g,_1);f5(3); }std::function
通過std::function對C++中各種可調用實體(普通函數、Lambda表達式、函數指針、以及其它函數對象等)的封裝,形成一個新的可調用的std::function對象;讓我們不再糾結那么多的可調用實體。
轉換后的std::function對象的參數能轉換為可調用實體的參數; 可調用實體的返回值能轉換為std::function對象的返回值。 std::function對象最大的用處就是在實現函數回調(實際工作中就是用到了這一點),使用者需要注意,它不能被用來檢查相等或者不相等,但是可以與NULL或者nullptr進行比較。
#include <functional> #include <iostream> using namespace std;std::function< int(int)> Functional;// 普通函數 int TestFunc(int a) { return a; }// Lambda表達式 auto lambda = [](int a)->int{ return a; };// 仿函數(functor) class Functor { public: int operator()(int a) { return a; } };// 1.類成員函數 // 2.類靜態函數 class TestClass { public: int ClassMember(int a) { return a; } static int StaticMember(int a) { return a; } };int main() { // 普通函數 Functional = TestFunc; int result = Functional(10); cout << "普通函數:"<< result << endl;// Lambda表達式 Functional = lambda; result = Functional(20); cout << "Lambda表達式:"<< result << endl;// 仿函數 Functor testFunctor; Functional = testFunctor; result = Functional(30); cout << "仿函數:"<< result << endl;// 類成員函數 TestClass testObj; Functional = std::bind(&TestClass::ClassMember, testObj, std::placeholders::_1); result = Functional(40); cout << "類成員函數:"<< result << endl;// 類靜態函數 Functional = TestClass::StaticMember; result = Functional(50); cout << "類靜態函數:"<< result << endl;return 0; }initializer_list
過往,我們這樣給vector賦值:
std::vector v; v.push_back(1); v.push_back(2); v.push_back(3); v.push_back(4);需要感謝的是,C++11讓你更方便。
std::vector v = { 1, 2, 3, 4 };這就是所謂的initializer list。更進一步,有一個關鍵字叫initializer list
#include <iostream> #include <vector> #include <map> #include <string> #include <typeinfo> class MyNumber { public:MyNumber(const std::initializer_list<int> &v) {for (auto itm : v) {mVec.push_back(itm);}}void print() {for (auto itm : mVec) {std::cout << itm << " ";}} private:std::vector<int> mVec; };class Test { public:void show(){for(auto kv : nameToBirthday){std::cout<<"key:\t"<<kv.first<<"\tvalue:\t"<<kv.second<<"\n";}} private:static std::map<std::string, std::string> nameToBirthday; }; std::map<std::string,std::string> Test::nameToBirthday = {{"lisi", "18841011"},{"zhangsan", "18850123"},{"wangwu", "18870908"},{"zhaoliu", "18810316"} };class CompareClass { public:CompareClass (int,int){std::cout<<"call old const\n";}CompareClass (std::initializer_list <int> ){std::cout<<"call initializer_list const\n";} };int main() {MyNumber m = { 1, 2, 3, 4 };m.print(); // 1 2 3 4Test t;t.show(); std::map<int,int> ii_map = {{1,1},{2,2}};CompareClass foo {10,20}; // calls initializer_list ctorCompareClass bar (10,20); // calls first constructor for(auto kv : ii_map){std::cout<<"key:\t"<<typeid(kv.first).name()<<"\n";}return 0; }thread
http://blog.csdn.net/tujiaw/article/details/8245130
#include <thread> void my_thread() {puts("hello, world"); }int main(int argc, char *argv[]) {std::thread t(my_thread);t.join();system("pause");return 0; }編譯命令 g++ -std=c++11 thread0.cpp -o thread0 -lpthread
實例化一個線程對象t,參數mythread是一個函數,在線程創建完成后將被執行,t.join()等待子線程mythread執行完之后,主線程才可以繼續執行下去,此時主線程會釋放掉執行完后的子線程資源。
#include <iostream> #include <stdlib.h> #include <thread> #include <string> #include <unistd.h>void my_thread(int num, const std::string& str) {std::cout << "num:" << num << ",name:" << str << std::endl; }int main(int argc, char *argv[]) {int num = 1234;std::string str = "tujiaw";std::thread t(my_thread, num, str);t.detach(); //子線程從主線程中分離出去 // sleep(1); return 0; }互斥量 多個線程同時訪問共享資源的時候需要需要用到互斥量,當一個線程鎖住了互斥量后,其他線程必須等待這個互斥量解鎖后才能訪問它。thread提供了四種不同的互斥量: 獨占式互斥量non-recursive (std::mutex) 遞歸式互斥量recursive (std::recursivemutex) 允許超時的獨占式互斥量non-recursive that allows timeouts on the lock functions(std::timedmutex) 允許超時的遞歸式互斥量recursive mutex that allows timeouts on the lock functions (std::recursivetimedmutex)
#include <iostream> #include <stdlib.h> #include <thread> #include <string> #include <mutex>int g_num = 0; std::mutex g_mutex;void thread1() {g_mutex.lock(); //線程加鎖g_num = 10;for (int i=0; i<10; i++){std::cout << "thread1:" << g_num <<"\tthread id:\t"<< std::this_thread::get_id() << std::endl;}g_mutex.unlock(); }void thread2() {std::lock_guard<std::mutex> lg(g_mutex); //自動鎖g_num = 20;for (int i=0; i<10; i++){std::cout << "thread2:" << g_num <<"\tthread id:\t"<< std::this_thread::get_id() << std::endl;} }int main(int argc, char *argv[]) {std::thread t1(thread1);std::thread t2(thread2);if(t1.joinable()) t1.join(); // t1.join(); // std::thread t3 = t2; //thread 對象禁止復制。 thread& operator= (const thread&) = delete; std::thread t3 = std::move(t2);if(t3.joinable()) t3.join();return 0; }std::thread 不僅能實現函數的綁定,成員函數,仿函數都可以。至于lambda 我就沒有試過了。
簡單的線程池實現
#include <iostream> #include <stdlib.h> #include <functional> #include <thread> #include <string> #include <mutex> #include <condition_variable> #include <vector> #include <memory> #include <assert.h> #include <algorithm> #include <queue>class ThreadPool {public:typedef std::function<void()> Task;ThreadPool(int num): num_(num), maxQueueSize_(0), running_(false){}~ThreadPool(){if (running_) {stop();}}ThreadPool(const ThreadPool&) = delete;void operator=(const ThreadPool&) = delete;void setMaxQueueSize(int maxSize){maxQueueSize_ = maxSize;}void start(){assert(threads_.empty());running_ = true;threads_.reserve(num_);for (int i = 0; i<num_; i++) {threads_.push_back(std::thread(std::bind(&ThreadPool::threadFunc, this)));}}void stop(){{std::unique_lock<std::mutex> ul(mutex_);running_ = false;notEmpty_.notify_all();}for (auto &iter : threads_) {iter.join();}}void run(const Task &t){if (threads_.empty()) {t();}else {std::unique_lock<std::mutex> ul(mutex_);while (isFull()) {notFull_.wait(ul);}assert(!isFull());queue_.push_back(t);notEmpty_.notify_one();}}private:bool isFull() const{return maxQueueSize_ > 0 && queue_.size() >= maxQueueSize_;}void threadFunc(){while (running_) {Task task(take());if (task) {std::lock_guard<std::mutex> lg(mutex_out); //自動鎖printf("thread id:%d\n", std::this_thread::get_id());task();printf("thread id:%d\n", std::this_thread::get_id());}}}Task take(){std::unique_lock<std::mutex> ul(mutex_);while (queue_.empty() && running_) {notEmpty_.wait(ul);}Task task;if (!queue_.empty()) {task = queue_.front();queue_.pop_front();if (maxQueueSize_ > 0) {notFull_.notify_one();}}return task;}private:int num_;std::mutex mutex_;std::mutex mutex_out;std::condition_variable notEmpty_;std::condition_variable notFull_;std::vector<std::thread> threads_;std::deque<Task> queue_;size_t maxQueueSize_;bool running_; };void fun() {printf("[id:%d] hello, world!\n", std::this_thread::get_id()); }int main() {{printf("main thread id:%d\n", std::this_thread::get_id());ThreadPool pool(3);pool.setMaxQueueSize(100);pool.start();//std::this_thread::sleep_for(std::chrono::milliseconds(3000));for (int i = 0; i < 1000; i++) {pool.run(fun);}std::this_thread::sleep_for(std::chrono::milliseconds(3000));}return 0; }atomic
原子操作
#include <thread> #include <atomic> #include <iostream> #include <time.h> #include <mutex> using namespace std; // 全局的結果數據 //long total = 0; std::atomic_long total(0); //std::mutex g_mutex;// 點擊函數 void click() {for(int i=0; i<1000000;++i){// 對全局數據進行無鎖訪問 // std::lock_guard<std::mutex> lg(g_mutex); //自動鎖total += 1; } }int main(int argc, char* argv[]) {// 計時開始clock_t start = clock();// 創建100個線程模擬點擊統計std::thread threads[100];for(int i=0; i<100;++i) {threads[i] = std::thread(click);}for(auto& t : threads){t.join();}// 計時結束clock_t finish = clock();// 輸出結果cout<<"result:"<<total<<endl;cout<<"duration:"<<finish -start<<"us"<<endl;return 0; }shared_ptr
這個sharedptr 相信大家都已經在boost中用過了。這里就不用詳細介紹了,反正是在能用原始指針的地方就能替換成 sharedptr。 #include?#include
struct Foo {Foo() { std::cout << "constructor Foo...\n"; }Foo(Foo&f) {std::cout<<"copy constructor Foo...\n";}void show(int i){std::cout<<"show Foo "<<i<<"\n";}~Foo() { std::cout << "~Foo...\n"; } };struct D { void operator()(Foo* p) const {std::cout << "Call delete for Foo object...\n";delete p;} };void needptr( Foo* fn,int i) {fn->show(i); }void needshptr(std::shared_ptr<Foo> shptr,int i) {shptr->show(i);std::cout<< shptr.use_count()<<'\n'; } int main() { // 只形成一個指針std::shared_ptr<Foo> sh1; //needptr(sh1.get(),1);auto shfn = std::make_shared<Foo>(); // 調用構造函數shfn->show(2); // std::shared_ptr<Foo> sh2(new Foo);std::shared_ptr<Foo> sh3(sh2);std::cout << sh2.use_count() << '\n';std::cout << sh3.use_count() << '\n';needshptr(sh3,3);std::cout << sh3.use_count() << '\n';//constructor with object and deleterstd::shared_ptr<Foo> sh4(new Foo, D()); }override和final關鍵字
override 強制檢查虛函數 final 禁止虛函數繼續重寫
高質量C++C 編程指南 訪問密碼 5de8
override 用法
#include <string> #include <iostream> #include <stdint.h> #include <stdio.h> class G {public:virtual void func(double a){ std::cout<<"G::func="<<a<<std::endl;} };class H:public G {public:int a;int b;void test(){ std::cout<<"Normal func"<<std::endl;} // 同名函數被隱藏了virtual void func(int a) //override //c++11 中添加這個關鍵字就能解決這一問題{ std::cout<<"H::func="<<a<<std::endl;} };typedef void (*FuncD)(double a); typedef void (*FuncI)(int a); typedef void (H::*Func)();//節選自 林銳博士的 《高質量C++C 編程指南》 8.2 章節 //重載的特征: // 1、處在相同的空間中,即相同的范圍內。 // 2、函數名相同。 // 3、參數不同,即參數個數不同,或相同位置的參數類型不同。 // 4、virtual 關鍵字對是否夠成重載無任何影響。 // 每個類維護一個自己的名字空間,即類域,所以派生類跟基類處于不同的空間之中,因些,雖然派生類自動繼承了基類的成員變量及成員函數,但基類的函數跟派生類的函數不可能直接夠成函數重載,因為它們處于兩個不同的域。 // // 隱藏規則: // 1、派生類的函數跟基類的函數同名,但是參數不同,此時,不論有沒有virtual關鍵字,基類函數將被隱藏。 // 2、派生類的函數跟基類的函數同名,且參數也樣,但基類沒有virtual關鍵字,此時基類函數也將被隱藏。//隱藏規則的底層原因其實是C++的名字解析過程。// 在繼承機制下,派生類的類域被嵌套在基類的類域中。派生類的名字解析過程如下: // 1、首先在派生類類域中查找該名字。 // 2、如果第一步中沒有成功查找到該名字,即在派生類的類域中無法對該名字進行解析,則編譯器在外圍基類類域對查找該名字的定義。 int main(int argc,char *argv[]) {H *h=new H;printf("%x\n",h);printf("%x\n",&H::test);printf("%x\n",&H::func);Func func=&H::test;(h->*func)();FuncD fund=(FuncD)(*(intptr_t*)*(intptr_t*)(h));FuncI funi=(FuncI)(*((intptr_t*)*(intptr_t*)(h)+1));printf("fund=%x\n",(intptr_t*)*(intptr_t*)(h));printf("funi=%x\n",((intptr_t*)*(intptr_t*)(h)+1));fund(10.1);funi(10);fund((G*)h,10.1); //需要綁定一個this指針,同時也把封裝性破壞了。funi(h,10);h->func(5);h->func(5.5);((g*)h)->func(5.5);h->G::func(5.5); return 0; }final 的用法
#include <iostream> using namespace std;class MathObject{public:virtual double Arith() = 0; // virtual void Print() final = 0 ; // 這樣寫會造成凡是派生自它的子類都無法創建對象virtual void Print() = 0 ;virtual void Print2(){cout<<"this is Print2()\n";}; };class Printable : public MathObject{public:double Arith() = 0;void Print() final// 在C++98中我們無法阻止該接口被重寫{cout << "Output is: " << Arith() << endl;} };class Add2 final: public Printable {public:Add2(double a, double b): x(a), y(b) {}double Arith() override final{ return x + y; }private:double x, y; };class Mul3 : public Printable {public:Mul3(double a, double b, double c): x(a), y(b), z(c) {}double Arith() { return x * y * z; } // void Print() 這里無法在改寫這個函數 // { // cout<<"Mul3 Print\n"; // }private:double x, y, z; };int main() {Add2 add2(2,3);cout<<"add2.Arith()"<<add2.Arith()<<'\n';add2.Print();Mul3 mul3(1,2,3);mul3.Print();return 0; }delete default
設置默認構造函數時使用。在類中定義了構造函數后,還想繼續使用默認構造函數,則可以在函數成員列表后添加 =default 。
可以使用在不允許使用復制構造函數和賦值構造函數上,則可以在函數成員列表后添加 =delete表示不定義。
#include <iostream>class NonCopyable { public:NonCopyable & operator=(const NonCopyable&) = delete;NonCopyable(const NonCopyable&) = delete;NonCopyable(int i){};NonCopyable() = default; // 不相當于用戶在寫一個 NonCopyable(void){};NonCopyable(double) = delete;void* operator new(size_t) = delete; // void* operator new[](size_t) = delete;//private:int m_i;};int main() {NonCopyable nc; // NonCopyable* pnc = new NonCopyable();NonCopyable *pncs = new NonCopyable[10]();std::cout<<sizeof(NonCopyable::m_i)<<std::endl; //sizeof 可以直接計算成員變量的大小,成員在外部必須可見。return 0; }正則
主類
這些類封裝了一個正則表達式和目標內的字符序列匹配正則表達式的結果.
basic_regex (C++11) 正則表達式對象 (類模板)
算法
使用這些功能應用正則表達式封裝在一個正則表達式的字符序列目標.. regexmatch 嘗試匹配正則表達式的整個字符序列 (函數模板) regexsearch 嘗試匹配正則表達式的字符序列的任何部分 函數模板) regex_replace 以格式化的替換文本來替換正則表達式匹配的地方(函數模板)
正則規則
#include <iostream> #include <iterator> #include <string> #include <regex> #include <fstream> #include <iterator> #include <vector> using VSS = std::vector<std::pair<std::string,std::string>> ;bool regex_search_all(std::string s,VSS& o , std::string reg_str) {std::regex r(reg_str);std::smatch m;bool ret = false;while(std::regex_search(s,m,r)){o.push_back(std::move(std::make_pair(m[0].str(),m[1].str())));s = m.suffix().str();ret = true;}return ret; } int main() {std::string s = "Some people, when confronted with a problem, think ""\"I know, I'll use regular expressions.\" ""Now they have two problems.";// 正則匹配std::regex self_regex("REGULAR EXPRESSIONS",std::regex_constants::ECMAScript | std::regex_constants::icase);if (std::regex_search(s, self_regex)) {std::cout << "Text contains the phrase 'regular expressions'\n";}std::ifstream in("360_20160114.xml", std::ios::in);std::istreambuf_iterator<char> beg(in), end;std::string strdata(beg, end);in.close();std::regex word_regex("(<pic_url>)\\s*(http://.*)\\s*(</pic_url>)");auto words_begin = std::sregex_iterator(strdata.begin(), strdata.end(), word_regex);auto words_end = std::sregex_iterator();std::cout << "Found " << std::distance(words_begin, words_end) << " words\n";for (std::sregex_iterator i = words_begin; i != words_end; ++i) {std::smatch match = *i;std::cout << " " << match.str() << '\n';}//正則捕獲std::string reg_str("<pic_url>\\s*(http://.*)\\s*</pic_url>");VSS vss;regex_search_all(strdata,vss,reg_str);for(auto kv : vss){std::cout<<kv.first<<'\t'<<kv.second<<'\n';}std::regex url_regex(reg_str);std::smatch m;while(std::regex_search(strdata,m,url_regex)){for(auto beg = m.begin(); beg != m.end();beg++){std::cout<<"匹配上:"<<beg->str()<<"\n";}strdata = m.suffix().str();}//正則替換std::regex long_word_regex("(\\w{7,})");std::string new_s = std::regex_replace(s, long_word_regex, "[$&]");std::cout << new_s << '\n'; }代碼2 #include?#include?#include
int main() {std::string fnames[] = {"foo.txt", "bar.txt", "baz.dat", "zoidberg"};std::regex pieces_regex("([a-z]+)\\.([a-z]+)");std::smatch pieces_match; for (const auto &fname : fnames) {if (std::regex_match(fname, pieces_match, pieces_regex)) {std::cout << fname << '\n';for (size_t i = 0; i < pieces_match.size(); ++i) {std::ssub_match sub_match = pieces_match[i];std::string piece = sub_match.str();std::cout << " submatch " << i << ": " << piece << '\n';} } } }輸出
foo.txtsubmatch 0: foo.txtsubmatch 1: foosubmatch 2: txt bar.txtsubmatch 0: bar.txtsubmatch 1: barsubmatch 2: txt baz.datsubmatch 0: baz.datsubmatch 1: bazsubmatch 2: datc++11 中vector 的新用法
修正過剩的容量
#include <vector> #include <iostream>void fun_old() {const int NUM = 1000;std::vector<int*> vec( NUM, nullptr );for(auto& e : vec){e = new int(42);}std::cout << "origin capacity: " << vec.capacity() << std::endl;std::cout << "first elem addr is " << vec[0] << std::endl;for(auto it = vec.begin() + 2; it != vec.end() ; it++){delete *it;*it = nullptr;}vec.erase(vec.begin() + 2, vec.end());std::vector<int*>( vec ).swap( vec );std::cout << "capacity after erase: " << vec.capacity() << std::endl;std::cout << "first elem addr is " << vec[0] << std::endl;for(auto e : vec){delete e;} }void fun_new() {const int NUM = 1000;std::vector<int*> vec( NUM, nullptr );for(auto& e : vec){e = new int(42);}std::cout << "origin capacity: " << vec.capacity() << std::endl;std::cout << "first elem addr is " << vec[0] << std::endl;for(auto it = vec.begin() + 2; it != vec.end() ; it++){delete *it;*it = nullptr;}vec.erase( vec.begin() + 2, vec.end() );vec.shrink_to_fit();std::cout << "capacity after erase: " << vec.capacity() << std::endl;std::cout << "first elem addr is " << vec[0] << std::endl;for(auto e : vec){delete e;} } int main() {fun_old();fun_new(); }直接構造元素
#include <vector> #include <string> #include <iostream> using namespace std; class Person {public:Person( string name ) : name_( name ) { }Person( const Person &other ) : name_( other.name_ ) {cout << "in copy constructor with name is " << name_ << endl;}Person(Person&& other) : name_( std::move(other.name_)){cout << "in move constructor with name is " << name_ << endl;}private:string name_; };int main() {std::vector<Person> vec;vec.reserve( 10 );cout<<"vec.push_back(Person(\"senlin\" ) )\n";vec.push_back( Person( "senlin" ) );cout<<"vec.push_back( p )\n";Person p( "zongming" );vec.push_back( p );cout<<"vec.push_back(Person(\"zhaoxiaobiao\"))\n";vec.push_back(Person("zhaoxiaobiao"));cout<<"vec.push_back(std::move(p))\n";vec.push_back(std::move(p));vec.push_back(std::move(Person("move")));cout<<"vec.emplace_back(\"zhaoxiaobiao\")\n";vec.emplace_back("zhaoxiaobiao"); }雖然華麗,但也讓人眼花繚亂。
總結
以上是生活随笔為你收集整理的c++11 你需要知道这些就够了的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 大明天下剧情介绍
- 下一篇: C++ override 关键字用法