原字符串
字符串前加’R’前缀 ,字符串首尾加上括号()
string path = "C:\\Program Files\\Microsoft.NET\\ADOMD.NET";
C++ 11
string path = R"(C:\Program Files\Microsoft.NET\ADOMD.NET)";
nullptr
用来区分空指针、0
区间迭代
vector<int> iVec;
for(auto i : iVec)
{
}
std::array
std::array 保存在栈内存中,相比堆内存中的 std::vector,我们能够灵活的访问这里面的元素,从而获得更高的性能.
std::array 会在编译时创建一个固定大小的数组,std::array 不能够被隐式的转换成指针,使用 std::array只需指定其类型和大小即可
std::array<int, 4> arr= {1,2,3,4};
int len = 4;
std::array<int, len> arr = {1,2,3,4}; // 非法, 数组大小参数必须是常量表达式
std::thread
编译需要使用 -pthread 选项,
join()主线程等待子线程结束方可执行下一步(串行),
detach()是的子线程放飞自我,独立于主线程并发执行
#include <iostream>
#include <thread>
void foo()
{
std::cout<<"in foo \n";
}
void bar(int x)
{
std::cout<<"in bar"<<x<<std::endl;
}
int main()
{
std::thread first(foo);
std::thread second(bar, 99);
first.join();
second.detach();
std::cout<<"end of main\n";
return 0;
}
新容器
unordered_set,unordered_map, unordered_multiset,和unordered_multimap
智能指针类
shared_ptr和unique_ptr
std::atomic
原子数据类型,原子数据类型不会发生数据竞争,能直接用在多线程中而不必我们用户对其进行添加互斥资源锁的类型
enable_shared_from_this
安全的返回this指针,对应boost::enable_shared_from_this
在构建智能指针时,尽量使用std::make_shared,相比直接new更安全、效率更高
#include <iostream>
#include <boost/shared_ptr.hpp>
class Test
{
public:
//析构函数
~Test() { std::cout << "Test Destructor." << std::endl; }
//获取指向当前对象的指针
boost::shared_ptr<Test> GetObject()
{
boost::shared_ptr<Test> pTest(this);
return pTest;
}
};
int main(int argc, char *argv[])
{
{
boost::shared_ptr<Test> p( new Test( ));
std::cout << "q.use_count(): " << q.use_count() << std::endl;
boost::shared_ptr<Test> q = p->GetObject();
}
return 0;
}
//程序输出,析构2次程序崩溃。
Test Destructor.
q.use_count(): 1
Test Destructor.
正确的实现
#include <memory>
#include <iostream>
struct Good : std::enable_shared_from_this<Good> // 注意:继承
{
public:
std::shared_ptr<Good> getptr() {
return shared_from_this();
}
~Good() { std::cout << "Good::~Good() called" << std::endl; }
};
int main()
{
// 大括号用于限制作用域,这样智能指针就能在system("pause")之前析构
{
std::shared_ptr<Good> gp1= std::make_shared<Good>();
std::shared_ptr<Good> gp2 = gp1->getptr();
// 打印gp1和gp2的引用计数
std::cout << "gp1.use_count() = " << gp1.use_count() << std::endl;
std::cout << "gp2.use_count() = " << gp2.use_count() << std::endl;
}
system("pause");
//程序输出,
gp1.use_count()=2
gp2.use_count()=2
"Good::~Good() called
C++ 可变参数列表 “…” 的使用
#include <iostream>
using namespace std;
void func2()
{
}
template <typename T, typename... U>
void func2(T v, U... args)
{
cout << v << endl;
func2(args...);
}
int main()
{
func2(1, 2, 3);
return 0;
}
lambda表达式
lambda表达式的基本格式
[capture list] (params list) mutable exception-> return type { function body }
lambda表达式的返回值通过返回值后置语法来定义,所以很多时候可以省略返回值类型,编译器根据return语句自动推导返回值类型。
[capture list] 捕获变量定义
[]不捕获任何变量;
[&]捕获外部作用域所有变量,并作为引用在函数体使用(按引用捕获);
[=]捕获外部作用域作用变量,并作为副本在函数体使用(按值捕获);
[]不捕获任何变量;
[&]捕获外部作用域所有变量,并作为引用在函数体使用(按引用捕获);
[=]捕获外部作用域作用变量,并作为副本在函数体使用(按值捕获);
auto f1 =[](WFHttpTask *task)
{
task->get_resp()->append_output_body("<html>Hello World liuxm!</html>");
}
[](int &a, int &b)->bool {
return a > b;
}
普通的lambda表达式后加一个(),可立刻执行对面的函数
std::move()
引用头文件
move是为了转移所有权,将一个左值强制转化为右值引用,将快要销毁的对象转移给其他变量,这样可以继续使用这个对象,而不必再创建一个一样的对象
使用的关键点
move(a),不应该再使用a这个变量,
std::string str = “Hello”;
std::vectorstd::string v;
v.push_back(std::move(str));