网站开发所需的知识,企业网站的开发建设方案怎么写,无法打开wordpress网页,wordpress 百度 taghttps://blog.csdn.net/tangliguantou/article/details/50549751c11新特性举着火把寻找电灯今天我就权当抛砖引玉#xff0c;如有不解大家一起探讨。有部分内容是引用自互联网上的内容#xff0c;如有问题请联系我。T 右值引用 std::move
右值引用出现之前我们只能…https://blog.csdn.net/tangliguantou/article/details/50549751c11新特性举着火把寻找电灯今天我就权当抛砖引玉如有不解大家一起探讨。有部分内容是引用自互联网上的内容如有问题请联系我。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给大家以提醒。其实c11在algorithm头文件也新增了一个move参数与意义都与此截然不同。
#include iostream
using namespace std;class HugeMem{public:HugeMem(int size): sz(size 0 ? size : 1) {c new int[sz];}~HugeMem() { coutHugeMem 析构\n;delete [] c; }HugeMem(HugeMem hm): sz(hm.sz), c(hm.c) {coutHugeMem move 构造\n;hm.c nullptr;}int * c;int sz;
};
class Moveable{public:Moveable():i(new int(3)), h(1024) {}~Moveable() { coutMoveable 析构\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
}早在C11之前编译器就把优化几乎做到了极致——局部变量返回到函数外部并赋值给外部变量这个过程基本上不存在任何多余的临时变量构造和析构这比move机制更加高效。显式指定move以后return std::move(localvar)这里会强行从localvar移动构造一个临时变量temp然后return temptemp这里会有RVO优化。
auto for循环
需要注意的是auto不能用来声明函数的返回值。但如果函数有一个尾随的返回类型时auto是可以出现在函数声明中返回值位置。这种情况下auto并不是告诉编译器去推断返回类型而是指引编译器去函数的末端寻找返回值类型。在下面这个例子中函数的返回值类型就是operator操作符作用在T1、T2类型变量上的返回值类型。
template typename T1, typename T2
auto compose(T1 t1, T2 t2) - **decltype**(t1 t2)
{return t1t2;
}
auto v compose(2, 3.14); // vs type is doubleauto与for配合使用
std::mapstd::string, std::vectorint map;
std::vectorint 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)是一个匿名函数即没有函数名的函数。
C11 的 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::vectorint 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 i4; };std::cout func1: func1(6) \n; // std::function 也可以接收lambda 表达式。std::functionint(int) func2 [](int i) { return i4; };std::cout func2: func2(6) \n; std::functionint() func3 [x]{return x;};std::cout func3: func3() \n;std::vectorint someList {1,2,3}; //这里是c11int 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 functionalvoid 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 n1n2 \n;}static void static_func(std::functionint(int) f,int n){std::coutcall static_func\n;std::coutf(n):\tf(n)\n;}int data 10; //c11 支持声明是就初始化值
};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);需要感谢的是C11让你更方便。
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_listint v) {for (auto itm : v) {mVec.push_back(itm);}}void print() {for (auto itm : mVec) {std::cout itm ;}}
private:std::vectorint mVec;
};class Test {
public:void show(){for(auto kv : nameToBirthday){std::coutkey:\tkv.first\tvalue:\tkv.second\n;}}
private:static std::mapstd::string, std::string nameToBirthday;
};
std::mapstd::string,std::string Test::nameToBirthday {{lisi, 18841011},{zhangsan, 18850123},{wangwu, 18870908},{zhaoliu, 18810316}
};class CompareClass
{
public:CompareClass (int,int){std::coutcall old const\n;}CompareClass (std::initializer_list int ){std::coutcall initializer_list const\n;}
};int main()
{MyNumber m { 1, 2, 3, 4 };m.print(); // 1 2 3 4Test t;t.show(); std::mapint,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::coutkey:\ttypeid(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 -stdc11 thread0.cpp -o thread0 -lpthread
实例化一个线程对象t参数mythread是一个函数在线程创建完成后将被执行t.join()等待子线程mythread执行完之后主线程才可以继续执行下去此时主线程会释放掉执行完后的子线程资源。
#include iostream
#include stdlib.h
#include thread
#include string
#include unistd.hvoid 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 mutexint g_num 0;
std::mutex g_mutex;void thread1()
{g_mutex.lock(); //线程加锁g_num 10;for (int i0; i10; i){std::cout thread1: g_num \tthread id:\t std::this_thread::get_id() std::endl;}g_mutex.unlock();
}void thread2()
{std::lock_guardstd::mutex lg(g_mutex); //自动锁g_num 20;for (int i0; i10; 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 queueclass ThreadPool
{public:typedef std::functionvoid() 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; inum_; i) {threads_.push_back(std::thread(std::bind(ThreadPool::threadFunc, this)));}}void stop(){{std::unique_lockstd::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_lockstd::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_guardstd::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_lockstd::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::vectorstd::thread threads_;std::dequeTask 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 i0; i1000000;i){// 对全局数据进行无锁访问
// std::lock_guardstd::mutex lg(g_mutex); //自动锁total 1; }
}int main(int argc, char* argv[])
{// 计时开始clock_t start clock();// 创建100个线程模拟点击统计std::thread threads[100];for(int i0; i100;i) {threads[i] std::thread(click);}for(auto t : threads){t.join();}// 计时结束clock_t finish clock();// 输出结果coutresult:totalendl;coutduration:finish -startusendl;return 0;
}shared_ptr
这个sharedptr 相信大家都已经在boost中用过了。这里就不用详细介绍了反正是在能用原始指针的地方就能替换成 sharedptr。 #include #include
struct Foo {Foo() { std::cout constructor Foo...\n; }Foo(Foof) {std::coutcopy constructor Foo...\n;}void show(int i){std::coutshow 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_ptrFoo shptr,int i)
{shptr-show(i);std::cout shptr.use_count()\n;
}
int main()
{ // 只形成一个指针std::shared_ptrFoo sh1; //needptr(sh1.get(),1);auto shfn std::make_sharedFoo(); // 调用构造函数shfn-show(2); // std::shared_ptrFoo sh2(new Foo);std::shared_ptrFoo 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_ptrFoo sh4(new Foo, D());
}override和final关键字
override 强制检查虚函数 final 禁止虚函数继续重写
高质量CC 编程指南 访问密码 5de8
override 用法
#include string
#include iostream
#include stdint.h
#include stdio.h
class G
{public:virtual void func(double a){ std::coutG::funcastd::endl;}
};class H:public G
{public:int a;int b;void test(){ std::coutNormal funcstd::endl;} // 同名函数被隐藏了virtual void func(int a) //override //c11 中添加这个关键字就能解决这一问题{ std::coutH::funcastd::endl;}
};typedef void (*FuncD)(double a); typedef void (*FuncI)(int a); typedef void (H::*Func)();//节选自 林锐博士的 《高质量CC 编程指南》 8.2 章节
//重载的特征
// 、处在相同的空间中即相同的范围内。
// 、函数名相同。
// 、参数不同即参数个数不同或相同位置的参数类型不同。
// 、virtual 关键字对是否够成重载无任何影响。
// 每个类维护一个自己的名字空间即类域所以派生类跟基类处于不同的空间之中因些虽然派生类自动继承了基类的成员变量及成员函数但基类的函数跟派生类的函数不可能直接够成函数重载因为它们处于两个不同的域。
//
// 隐藏规则
// 、派生类的函数跟基类的函数同名但是参数不同此时不论有没有virtual关键字基类函数将被隐藏。
// 、派生类的函数跟基类的函数同名且参数也样但基类没有virtual关键字此时基类函数也将被隐藏。//隐藏规则的底层原因其实是的名字解析过程。// 在继承机制下派生类的类域被嵌套在基类的类域中。派生类的名字解析过程如下
// 、首先在派生类类域中查找该名字。
// 、如果第一步中没有成功查找到该名字即在派生类的类域中无法对该名字进行解析则编译器在外围基类类域对查找该名字的定义。
int main(int argc,char *argv[])
{H *hnew H;printf(%x\n,h);printf(%x\n,H::test);printf(%x\n,H::func);Func funcH::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(){coutthis is Print2()\n;};
};class Printable : public MathObject{public:double Arith() 0;void Print() final// 在C98中我们无法阻止该接口被重写{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() 这里无法在改写这个函数
// {
// coutMul3 Print\n;
// }private:double x, y, z;
};int main()
{Add2 add2(2,3);coutadd2.Arith()add2.Arith()\n;add2.Print();Mul3 mul3(1,2,3);mul3.Print();return 0;
}delete default
设置默认构造函数时使用。在类中定义了构造函数后还想继续使用默认构造函数则可以在函数成员列表后添加 default 。
可以使用在不允许使用复制构造函数和赋值构造函数上则可以在函数成员列表后添加 delete表示不定义。
#include iostreamclass 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::coutsizeof(NonCopyable::m_i)std::endl; //sizeof 可以直接计算成员变量的大小成员在外部必须可见。return 0;
}正则
主类
这些类封装了一个正则表达式和目标内的字符序列匹配正则表达式的结果.
basic_regex C11 正则表达式对象 类模板
算法
使用这些功能应用正则表达式封装在一个正则表达式的字符序列目标.. regexmatch 尝试匹配正则表达式的整个字符序列 函数模板 regexsearch 尝试匹配正则表达式的字符序列的任何部分 函数模板 regex_replace 以格式化的替换文本来替换正则表达式匹配的地方(函数模板
正则规则
#include iostream
#include iterator
#include string
#include regex
#include fstream
#include iterator
#include vector
using VSS std::vectorstd::pairstd::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, Ill 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_iteratorchar 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::coutkv.first\tkv.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: datc11 中vector 的新用法
修正过剩的容量
#include vector
#include iostreamvoid fun_old()
{const int NUM 1000;std::vectorint* 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::vectorint*( 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::vectorint* 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::vectorPerson vec;vec.reserve( 10 );coutvec.push_back(Person(\senlin\ ) )\n;vec.push_back( Person( senlin ) );coutvec.push_back( p )\n;Person p( zongming );vec.push_back( p );coutvec.push_back(Person(\zhaoxiaobiao\))\n;vec.push_back(Person(zhaoxiaobiao));coutvec.push_back(std::move(p))\n;vec.push_back(std::move(p));vec.push_back(std::move(Person(move)));coutvec.emplace_back(\zhaoxiaobiao\)\n;vec.emplace_back(zhaoxiaobiao);
}虽然华丽但也让人眼花缭乱。