常用新特性汇总
C++11常用新特性快速一览_jiange_zh的博客-优快云博客_c++11新特性
C++11 FAQ中文版
std::function 和 std::bind | C++11 FAQ 中文版
GitBook - Where software teams break knowledge silos.
typename std::enable_if
std::is_integral
std::is_same
智能指针
shared_ptr, make_shared, shared_from_this
Smart pointers (Modern C++) | Microsoft Docs
How to: Create and use shared_ptr instances | Microsoft Docs
智能指针shared_ptr的用法 - jiayayao - 博客园
c++11中的shared_from_this
C++11新特性之十:enable_shared_from_this_草上爬的博客-优快云博客_std::enable_shared_from_this
std::enable_shared_from_this<T>::shared_from_this - cppreference.com
weak_ptr是shared_ptr的弱引用,如果shared_ptr只会根据shared_ptr之间的引用来释放,而不会判断weak_ptr对shared_ptr的引用,weak_ptr主要是链表这种相互引用的场景容易导致double free。而unique_ptr主要是类内部成员使用,性能比shared_ptr更好,因此不传递对象时优先使用unique_ptr。
raw指针需要手动new delete
而智能指针可以自动在不需要时删除对象,不用显示调用delete。
#include <memory>
class A: public std::enable_shared_from_this{
}
这里public 功能如下,如果pa是智能指针,a是*pa,则可以反过来从a获得pa。
智能指针循环依赖问题
#include <iostream>
#include <map>
#include <string>
#include <vector>
#include <memory>
using namespace std;
class A {
public:
string name;
A(string name):name( name) {
cout << name << " is created" << endl;
}
~A() {
cout << name << " is distroyed" << endl;
}
std::shared_ptr<A> next = nullptr;
static std::shared_ptr<A> newA(string name) {
return std::make_shared<A>(name);
}
};
using APtr = std::shared_ptr<A>;
int main() {
APtr A = A::newA("A");
APtr B = A::newA("B");
A->next = B;
B->next = A;
return 0;
}
链表里面可能会出现上述场景,这会导致A和B均无法被释放。
修改方法:将上面类里面next对象从std::shared_ptr next = nullptr;改成std::weak_ptr next;即可
unique_ptr管理数组和指针
std::unique_ptr<int[]> data_buf = std::make_unique<int[]>(elem_num);
std::unique_ptr<int> data_buf1 = std::make_unique<int>(12);
基于unique_ptr智能指针管理文件和数组example(from tflite):
#include <iostream>
#include <string>
#include <sys/stat.h>
using namespace std;
int main() {
const char* filename = "/root/codes/models/linear.tflite";
std::unique_ptr<const char[]> copied_buffer_;
size_t buffer_size_bytes_ = 0;
// Obtain the file size using fstat, or report an error if that fails.
std::unique_ptr<FILE, decltype(&fclose)> file(fopen(filename, "rb"), fclose);
if (!file) {
printf("Could not open '%s'.", filename);
exit(1);
}
struct stat sb;
// support usage of msvc's posix-like fileno symbol
#ifdef _WIN32
#define FILENO(_x) _fileno(_x)
#else
#define FILENO(_x) fileno(_x)
#endif
if (fstat(FILENO(file.get()), &sb) != 0) {
printf("Failed to get file size of '%s'.", filename);
exit(1);
}
#undef FILENO
buffer_size_bytes_ = sb.st_size;
std::unique_ptr<char[]> buffer(new char[buffer_size_bytes_]);
if (!buffer) {
printf("Malloc of buffer to hold copy of '%s' failed.", filename);
exit(1);
}
size_t bytes_read = fread(buffer.get(), sizeof(char), buffer_size_bytes_, file.get());
if (bytes_read != buffer_size_bytes_) {
printf("Read of '%s' failed (too few bytes read).", filename);
exit(1);
}
// Versions of GCC before 6.2.0 don't support std::move from non-const
copied_buffer_.reset(const_cast<char const*>(buffer.release()));
std::cout << "hello" << std::endl;
return 1;
}
枚举类型声明
enum E : unsigned int ;
c++11:枚举类型(enum)的前向声明(forward declaration) - 腾讯云开发者社区-腾讯云
c++ vector释放内存
Delete vector contents and free up memory in C++ | Techie Delight
v.clear()
v.shrink_to_fit();
string wstring相互转换
c++ - How to convert wstring into string? - Stack Overflow
#include <string>
#include <locale>
#include <codecvt>
// convert string to wstring
inline std::wstring to_wide_string(const std::string& input)
{
std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
return converter.from_bytes(input);
}
// convert wstring to string
inline std::string to_byte_string(const std::wstring& input)
{
//std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
return converter.to_bytes(input);
}
wstring wstr = L"中国人";
cout << "unicode编码:" << wstr.c_str() << endl;
随机数生成
[C++11]C++11带来的随机数生成器 - egmkang - 博客园
Pseudo-random number generation - cppreference.com
设置seed
#include <random>
#include <iostream>
using namespace std;
std::random_device rand_seed;
std::mt19937 mt;
//std::mt19937 mt(rand_seed());
int init_num = 20;
mt.seed(1);
for (int i = 0; i < init_num; i++) {
cout << dist_fp32(mt) << " ";
}
cout << endl;
mt.seed(rand_seed());
for (int i = 0; i < init_num; i++) {
cout << dist_fp32(mt) << " ";
}
cout << endl;
std::random_device r;
std::seed_seq seed{r()};
std::mt19937 rng(seed);
std::uniform_real_distribution<float> rand_distrib(-1, 1);
多线程
C++11 Concurrency Tutorial - Part 5: Futures | Blog blog("Baptiste Wicht");
C++多线程类Thread(C++11)_ouyangfushu的博客-优快云博客_c++11 thread
获取多线程返回值:
(原创)用C++11的std::async代替线程的创建 - qicosmos(江南) - 博客园
简单范例:
#include <thread>
#include <future>
std::string simplefunc(std::string a){
return a;
}
int main(){
auto future = std::async(std::launch::async, simplefunc, "hello world");
std::string simple = future.get();
cout<<simple<<endl;
return 0;
}
线程函数可以传指针不能传引用。
std::launch::async:在调用async就开始创建线程。
std::launch::deferred:延迟加载方式创建线程。调用async时不创建线程,直到调用了future的get或者wait时才创建线程。
锁mutex lock_guard的使用
C++锁的管理-- std::lock_guard和std::unique_lock_未来之歌-优快云博客_lock_guard<std::mutex>
线程延时
#include <iostream>
#include <chrono>
#include <thread>
std::this_thread::sleep_for(chrono::seconds(2));
std::this_thread::sleep_for(std::chrono::milliseconds(3000));
std::condition_variable
C++11 并发指南五(std::condition_variable 详解) - Haippy - 博客园
lambda表达式
std::bind, std::function
ttps://www.jianshu.com/p/f191e88dcc80
C++11:std::bind_秋叶原 && Mike || 麦克-优快云博客
c++ - std::function and std::bind: what are they, and when should they be used? - Stack Overflow
基于bind,function和random实现不同随机数生成方式
int seed = 1;
float range0 = 0;
float range1 = 10;
std::mt19937 mt(seed);
std::uniform_real_distribution<float> unoform_rand(range0, range1);
std::normal_distribution<> normal_rand(range0, range1);
std::function<float()> rand_generator = bind(unoform_rand, mt);
for (int i = 0; i < 10; i++) {
cout << rand_generator() << " ";
}
cout << endl;
rand_generator = std::bind(normal_rand, mt);
for (int i = 0; i < 10; i++) {
cout << rand_generator() << " ";
}
cout << endl;
执行时间测量
optimization - Measuring execution time of a function in C++ - Stack Overflow
#include <iostream>
#include <chrono>
// duration TYPES
// using nanoseconds = duration<long long, nano>;
// using microseconds = duration<long long, micro>;
// using milliseconds = duration<long long, milli>;
// using seconds = duration<long long>;
// using minutes = duration<int, ratio<60>>;
// using hours = duration<int, ratio<3600>>;
int main()
{
auto t1 = std::chrono::high_resolution_clock::now();
function();
auto t2 = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>( t2 - t1 ).count();
double cur_time = std::chrono::duration_cast<std::chrono::microseconds>(t2.time_since_epoch()).count()/1000000.0;
std::cout << duration;
return 0;
}
获取当前时间C++ chrono system time in milliseconds, time operations - Stack Overflow
auto now = std::chrono::system_clock::now();
auto duration = now.time_since_epoch();
auto in_time_t = std::chrono::system_clock::to_time_t(now);
auto micros = std::chrono::duration_cast<std::chrono::microseconds>(duration).count();
std::cout << in_time_t << std::endl;
printf("time:%.6f\n", micros / 1000000.0);
文件创建时间转换到long long用于比较
#include <chrono>
#include <filesystem>
#include <fstream>
#include <iostream>
string file_path = "D:\\option.ini";
std::filesystem::file_time_type ftime = std::filesystem::last_write_time(file_path);
auto duration = ftime.time_since_epoch();
// create time since 1970.1.1
long long create_time_since_epoch = std::chrono::duration_cast<std::chrono::seconds>(duration).count();
cout << "create_time_since_epoch:" << create_time_since_epoch << endl;
vector of reference
c++ - Why can't I make a vector of references? - Stack Overflow
过去是无法使用 vector vec的。但是C++11提供了解决方案
#include <iostream>
#include <vector>
#include<functional>
using namespace std;
int main() {
std::vector<std::reference_wrapper<int>> data;
int a = 1;
data.push_back(a); // std::ref(a)
data[0].get() = 100;
cout << a << endl;
return 0;
}
hash函数 std::hash - cppreference.com
#include <iostream>
#include <functional>
#include <string>
std::size_t h1 = std::hash<std::string>{}(s.first_name);
std::call_once
C++11中的std::call_once_爱很遥远-优快云博客_c++ call_once
右值引用
什么是move?理解C++ Value categories,move, move in Rust - 知乎
std:;move, std::swap, 拷贝构造函数
StorageView& operator=(const StorageView& other);
StorageView& operator=(StorageView&& other) noexcept;
StorageView(StorageView&& other) noexcept
序列初始化
std::vector<size_t> example_index(global_batch_size);
std::iota(example_index.begin(), example_index.end(), 0);
第三方扩展库
absl::optional
https://github.com/progschj/ThreadPool/tree/master
-------------------------
c++常用功能
可以在class对成员变量赋默认值。
最好将基类的析构函数,以及其他需要被继承的函数写成虚函数,否则多态容易出错。
dlopen加载动态库
test1.h
#pragma once
#include <iostream>
#include <string>
using namespace std;
class Engine {
public:
string name;
int data;
Engine();
};
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
Engine* CreateEngine();
void DelEngine(Engine* engine);
#ifdef __cplusplus
}
#endif /* __cplusplus */
test1.cpp
#include "test1.h"
Engine::Engine() {
name = "engine";
data = 2;
}
Engine* CreateEngine() {
Engine* engine = new Engine;
return engine;
}
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void DelEngine(Engine* engine) { delete engine; }
#ifdef __cplusplus
}
#endif /* __cplusplus */
main.cpp
#include <iostream>
#include <string>
#include <dlfcn.h>
using namespace std;
#include "test1.h"
int main() {
// dlopen can find file in LD_LIBRARY_PATH
string lib_path = "libtestengine.so";
void* handle = dlopen(lib_path.c_str(), RTLD_LAZY);
decltype(CreateEngine)* create_engine;
decltype(DelEngine)* destroy_engine;
create_engine = (decltype(CreateEngine)*)dlsym(handle, "CreateEngine");
destroy_engine = (decltype(DelEngine)*)dlsym(handle, "DelEngine");
Engine* engine = (Engine*)create_engine();
cout << engine->name << ", " << engine->data << endl;
destroy_engine(engine);
return 0;
}
utility
fp16库
half: Half-precision floating-point library
FP16/third-party at master · Maratyszcza/FP16 · GitHub
执行shell命令 system和popen,可以用于执行shell命令,间接获取文件夹下文件名称等
Linux下使用popen()执行shell命令 - 功夫Panda - 博客园
std::system - cppreference.com
C++ STL正确删除元素方法
vector<int> data = { 1,2,3,4,5,6,7,8 };
for (auto itr = data.begin(); itr != data.end();) {
if (*itr == 8) {
itr=data.erase(itr);
}
else {
itr++;
}
}
data.erase(itr);itr++,或者data.erase(itr++)均不可取!!!处理最后一个元素可能有意外。
dlopen调用C++函数解释
https://www.tldp.org/HOWTO/pdf/C++-dlopen.pdf
nlohmann json解析文件 GitHub - nlohmann/json: JSON for Modern C++
#include "nlohmann/json.hpp"
using namespace nlohmann;
ifstream jsonFile(fileName);
jsonData = json::parse(jsonFile);
jsonData = json::parse(dumpString);
基本类型数据解析:
float data= jsonData[key];
map,vector类型解析:
map data= jsonData[key].get>();
直接存储的dict list解析
for (auto& element : jsonData) {
std::cout << element["op"] << '\n';
}
note: 需要加try catch异常处理。
c++字符串替换
string - Replace substring with another substring C++ - Stack Overflow
#include <string>
#include <regex>
std::string test = "{abc def abc def}";
test = std::regex_replace(test, std::regex("def"), "klm");
test = std::regex_replace(test , std::regex("\\{"), "(");
test = std::regex_replace(test , std::regex("\\}"), ")");
注意双反斜杠的使用https://www.softwaretestinghelp.com/regex-in-cpp/
多个匹配模式提取c++ - Splitting a string by a character - Stack Overflow
字符串split C++ - Split string by regex - Stack Overflow
std::regex rgx(":");
std::sregex_token_iterator iter(string_to_split.begin(),
string_to_split.end(),
rgx,
-1);
std::sregex_token_iterator end;
for ( ; iter != end; ++iter)
std::cout << *iter << '\n';
如果没有匹配到任何split符号会死循环
#include <string>
#include <algorithm> // copy
#include <iterator> // back_inserter
#include <regex> // regex, sregex_token_iterator
#include <vector>
int main()
{
std::string str = "08/04/2012";
std::vector<std::string> tokens;
std::regex re("[-\\d]+");
//start/end points of tokens in str
std::sregex_token_iterator
begin(str.begin(), str.end(), re),
end;
std::copy(begin, end, std::back_inserter(tokens));
}
C++中的#和##
C++中的#和##_zhang_chou_chou的博客-优快云博客_c++中##
c++实现数组每个元素解压出来作为函数参数unpact array and use the elements as function parameters
实现类似python的效果(f的输入参数是3个元素)
args = [1,2,4]
f(*args)
Any Solution to Unpack a Vector to Function Arguments in C++? - Stack Overflow
在 C++ 中解包 std::vector 作为函数参数 | 始终
类成员函数末尾const修饰:
C++成员函数末尾const关键字…_程序猿进化史-优快云博客_c++函数末尾const
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class A {
public:
string GetName(string name) {
return "not const name:" + name;
}
string GetName(string name) const{
return "const name:" + name;
}
};
int main() {
A a1;
cout << a1.GetName("lll") << endl;
const A a2;
cout << a2.GetName("lll") << endl;
return 0;
}
const和非const修饰的函数可以同时存在;非const成员可以调用带有const修饰的函数(如果没有对应的不带const修饰的函数)
上面的代码段中,a1和a2将分别调用不带const和带const的函数。
如果删除不带const的函数,则都调用带const的版本。但是如果删除带const的函数,则a2调用会报错。
头文件环境变量
export CPLUS_INCLUDE_PATH=$CLUS_INCLUDE_PATH:/usr/local/cuda-10.0/include/
c++ fp16库:http://half.sourceforge.net/ 采用MIT License
程序从启动当当前运行时间:
#include<ctime>
clock_t startTime = clock();
Lambda表达式 https://www.cnblogs.com/jimodetiantang/p/9016826.html
正则表达式
字符串替换
string shape_str = "[?,?,14,14]";
shape_str = std::regex_replace(shape_str, std::regex("\\?"), "-1");
do while妙用
do{...}while(0)的妙用 - lizhenghn - 博客园
模板
指针类型如void*用到模板里面可能出现const void**无法匹配等问题,可以考虑使用using void_ptr=void*把类型打包创新新类型避免模板匹配异常。
vector find:
c++ - How to find out if an item is present in a std::vector? - Stack Overflow
std::find(vec.begin(), vec.end(), item) != vec.end()
代码格式化
clang-format参考使用clang-format格式化你的代码 · hokein
修改为clang-format-7
apt-get install clang-format-7 (其他系统版本可能apt-get install clang-format)
clang-format-7 -i xxx.cpp -style=Google
保存配置文件:
clang-format -style=Google -dump-config > .clang-format
配置文件修改
tab size
SortIncludes: false
加载配置文件进行格式化(自动从当前向上层目录寻找.clang-format配置文件):
clang-format-7 -style=file -i xxx.cpp
c++ - How do I specify a clang-format file? - Stack Overflow
clion代码格式化
Ctrl+Alt+S修改设置
Ctrl+Alt+L处理单个文件
工程上右键选择Reformat code
Google 开源项目风格指南——中文版 — Google 开源项目风格指南
sublime text 格式化工具
SublimeAStyleFormatter google风格配置
"style": "google",
"attach-namespaces": true,
"attach-classes": true,
"indent-switches": true,
"pad-header": true,
"align-pointer": "type",
"unpad-paren": true,