C++11 常用新特性

常用新特性汇总

我在项目中经常使用的c++11新特性 - 知乎

C++11常用新特性快速一览_jiange_zh的博客-CSDN博客_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++ 智能指针的正确使用方式 | 编程沉思录

c++11中的shared_from_this

C++11新特性之十:enable_shared_from_this_草上爬的博客-CSDN博客_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;
}

C++11新增alignas关键字作用 – 梁笔记

枚举类型声明

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 <iostream>
#include <string>
#include <locale> 
#include<codecvt>

std::wstring s2ws(const std::string& str)
{
    using convert_typeX = std::codecvt_utf8<wchar_t>;
    std::wstring_convert<convert_typeX, wchar_t> converterX;

    return converterX.from_bytes(str);
}

std::string ws2s(const std::wstring& wstr)
{
    using convert_typeX = std::codecvt_utf8<wchar_t>;
    std::wstring_convert<convert_typeX, wchar_t> converterX;

    return converterX.to_bytes(wstr);
}

随机数生成

[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的博客-CSDN博客_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_未来之歌-CSDN博客_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表达式

C++ 11 Lambda表达式 - 滴水瓦 - 博客园

std::bind, std::function

std::bind - cppreference.com

ttps://www.jianshu.com/p/f191e88dcc80

C++11:std::bind_秋叶原 && Mike || 麦克-CSDN博客

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_爱很遥远-CSDN博客_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

GitHub - bshoshany/thread-pool: BS::thread_pool: a fast, lightweight, and easy-to-use C++17 thread pool library

-------------------------

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的博客-CSDN博客_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关键字…_程序猿进化史-CSDN博客_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 格式化工具

GitHub - timonwong/SublimeAStyleFormatter: SublimeAStyleFormatter is a code formatter/beautifier for Sublime Text 2 & 3. It provides ability to format C/C++/C#/Java files.

SublimeAStyleFormatter google风格配置

        "style": "google",

       "attach-namespaces": true,

        "attach-classes": true,

        "indent-switches": true,
        "pad-header": true,
        "align-pointer": "type",
        "unpad-paren": true,

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: C 11 新特性是指 C 语言的第 11 版本(也称为 C11),它引入了一些新的功能和改进,以提高 C 语言的使用性和性能。 首先,C 11 新特性中引入了线程支持。C 语言之前的版本没有原生的线程支持,但在 C11 中引入了线程库,使得开发者可以使用线程来并发执行不同的任务,从而提高程序的效率。 其次,C 11 新特性中还引入了原子操作。原子操作是指一种无法被中断的操作,它可以保证在多线程环境下的数据一致性和同步。C 11 提供了一些原子操作的函数和类型,使得开发者能够更方便地处理多线程编程中的共享数据和临界区问题。 此外,C 11 还引入了泛型选择表达式(Generic Selection Expression)。泛型选择表达式允许在编译时根据不同的类型执行不同的操作,这样可以提高代码的复用性和灵活性。开发者可以根据需要定义不同的操作和类型,然后在程序中使用泛型选择表达式来选择合适的操作。 最后,C 11 新特性还包括对 C 语言标准库的一些改进和增强。例如,C 11 引入了一些新的数学库函数、字符串处理函数、输入输出函数等,使得开发者能够更方便地进行数值计算、字符串处理和文件读写等操作。 综上所述,C 11 新特性为开发者提供了更强大和便捷的工具,使得 C 语言在并发编程、数据处理和算法实现方面具有更高的性能和灵活性。 ### 回答2: C 11中的新特性主要包括对C语言的增强和扩展,其中也包括了对PDF的支持。 首先,C 11对语言本身进行了改进。它提供了更丰富的数据类型支持,包括_Bool、_Imaginary和_Complex等新的数据类型,使得程序员能够更方便地处理复杂的数据。此外,C 11还引入了泛型选择表达式(Generic Selection Expression),使得代码能够更加灵活和通用。 其次,C 11还引入了对多线程编程的支持。它提供了线程库和原子操作函数,使得并发编程更加容易,能够充分利用多核处理器的计算能力,提高程序的性能。这对于需要处理大规模数据和实时计算的应用来说非常重要。 另外,C 11还加入了对PDF的支持。PDF(Portable Document Format)是一种常用的文档格式,C 11通过引入一些新的函数和数据类型,使得程序可以更方便地处理PDF文件。例如,C 11提供了一些用于读写PDF文件的函数接口,使得程序能够直接读取和修改PDF文件中的内容,实现对PDF文件的灵活处理。 总之,C 11的新特性不仅增强了C语言本身的功能和性能,还为开发者提供了更多的选择和便利,包括更丰富的数据类型支持、多线程编程和对PDF的处理。这些特性使得C 11成为一个更强大和适用的编程语言,在许多应用领域中得到了广泛的应用和推广。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Luchang-Li

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值