锐英源软件
第一信赖

精通

英语

开源

擅长

开发

培训

胸怀四海 

第一信赖

当前位置:锐英源 / 开源技术 / C++开源 / C++17归类引导、C++17性能提升关键点示例
联系方式
固话:0371-63888850
手机:138-0381-0136
Q Q:396806883
微信:ryysoft

锐英源精品开源心得,禁止全文或局部转载,禁止任何形式的非法使用,侵权必究


C++17归类引导、C++17性能提升关键点示例


本文介绍C++17知识点的名称,不讲解大多细节,只讲解C++性能提升关键点示例。因为我最近写的项目,很多线程,想要提升性能。所以叫:C++17归类引导、C++17性能提升关键点示例。

C++17归类有:

结构结合
带有初始值设定项的 'if' 和 'switch' 语句
Constexpr lambda 并按值捕获 *this
if constexpr
__has_include
使用不重复的属性命名空间
属性 'nodiscard', 'fallthrough', 'maybe_unused'
std::string_view
嵌套的 'namespaces'
字符串转换
过度对齐的动态内存分配
折叠表达式
'inline' 变量
库添加
文件系统
并行算法

C++性能提升关键点中重要的有字符串转换和并行算法,这里对字符串转换进行示例讲解,因为字符串是最常用的功能。

字符串转换

当然,在以前的 C++ 标准中,总是有字符串转换函数,比如:std::atoi, std::atol, std::atoll, std::stoi, std::stol, std::stoll, std::sprintf, std::snprintf, std::stringstream, std::sscanf, std::strtol, std::strtoll, std::stringstream, std::to_string遗憾的是,这些功能在性能方面不够有效。
一般认为,上述函数对于复杂字符串的处理,例如对于复杂数据格式(如 JSON 或 XML)的高效处理,速度较慢。
特别是当此类数据格式用于通过网络进行通信时,其中高带宽是一个关键因素。
在 C++17 中,我们得到了两组函数:from_chars和to_chars,它们允许低级字符串转换并显著提高性能。
例如,Microsoft 报告说 C++17 已针对科学记数法进行了改进,它的floating-point to_chars()速度大约是 sprintf_s() “%.8e” 的 10 倍,是 sprintf_s() “%.16e”处理double 的 30 倍。这使用了Ulf Adams的新算法 Ryu。
注意:如果您使用的是 Visual Studio 2017,则需要确保已安装 15.8 或更早版本,因为版本 15.7(具有第一个完整的 C++17 库支持)不支持 <charconv> 标头。
让我们看一个例子,了解如何使用 ,使用 ,将字符串转换为整数和浮点数:std::from_chars

#include <iostream>
#include <string>
#include <array>
#include <charconv> // from_chars
               
int main() 
{
	std::cout << "---------------------------------------------------------------------------------------------------\n";
	std::cout << "Let's demonstrate string conversion to integer using the 'std::from_chars' function " << std::endl;
	std::cout << "---------------------------------------------------------------------------------------------------\n";

	std::array<std::string, 8> arrIntNums = { std::string("-123"),
                              std::string("-1234"),
                              std::string("-12345"),
                              std::string("-1234567890987654321"),
                              std::string("123"),
                              std::string("1234"),
                              std::string("1234567890"),
                              std::string("1234567890987654321")};//8是数组长度
	int stored_int_value { 0 };
	for (auto& e : arrIntNums)
	{
		std::cout << "Array element = " << e << std::endl;
		const auto res = std::from_chars(e.data(), e.data() + e.size(), 
                         stored_int_value /*, int base = 10*/);

		switch (res.ec)
		{
			case std::errc():  //from_chars的结果是复杂类型,不是直接数值类型
				std::cout << "Stored value: " << stored_int_value << ", 
                Number of characters = " << res.ptr - e.data() << std::endl;//正常状态,输出结果
				break;
			case std::errc::result_out_of_range:  
				std::cout << "Result out of range! 
                Number of characters = " << res.ptr - e.data() << std::endl;
				break;	
			case std::errc::invalid_argument:
				std::cout << "Invalid argument!" << std::endl;
				break;
			default:  
				std::cout << "Error: res.ec = " << int(res.ec) << std::endl;
		}
	}

	std::cout << "\n---------------------------------------------------------------------------------------------------";
	std::cout << "\nLet's demonstrate string conversion to double using the 'std::from_chars' function ";
	std::cout << "\n---------------------------------------------------------------------------------------------------\n";

	std::array<std::string, 8=""> arrDoubleNums = { std::string("4.02"),
                                 std::string("7e+5"),
                                 std::string("A.C"),
                                 std::string("-67.90000"),
                                 std::string("10.9000000000000000000000"),
                                 std::string("20.9e+0"),
                                 std::string("-20.9e+1"),
                                 std::string("-10.1") };
	double stored_dw_value { 0.0 };
	for (auto& e : arrDoubleNums)
	{
		std::cout << "Array element = " << e << std::endl;
		const auto res = std::from_chars(e.data(), e.data() + e.size(), 
                         stored_dw_value, std::chars_format::general);

		switch (res.ec)
		{
		case std::errc():
			std::cout << "Stored value: " << stored_dw_value << ", 
                 Number of characters = " << res.ptr - e.data() << std::endl;
			break;
		case std::errc::result_out_of_range:
			std::cout << "Result out of range! Number of characters = " 
                      << res.ptr - e.data() << std::endl;
			break;
		case std::errc::invalid_argument:
			std::cout << "Invalid argument!" << std::endl;
			break;
		default:
			std::cout << "Error: res.ec = " << int(res.ec) << std::endl;
		}
	}
	
	return 0;
} 

请注意,在第二次调用std::from_chars时,最后参数我们使用额外的std::chars_format::general,以支持不同的数字格式串。
std::chars_format::general(在 <charconv> 中定义)用于指定std::to_chars 和std::from_chars 函数的浮点格式的 。
让我们看看上面代码的输出,将字符串转换为整数和双精度:

现在让我们做相反的操作,即考虑一个示例,说明我们如何使用std::to_chars来将整数和浮点数转换为字符串:

#include <iostream>
#include <string>
#include <array>
#include <charconv> // to_chars 
          
int main() 
{
     std::cout << "--------------------------------------------------------------------------------------------------------------------\n";
     std::cout << "Let's demonstrate the conversion of long values to a string (5 characters long) using the 'std::to_chars' function " << std::endl;
     std::cout << "--------------------------------------------------------------------------------------------------------------------\n";
     
     // construction uses aggregate initialization
     std::array<long, 8=""> arrIntNums = { -123,-1234,-12345, -1234567890, 123, 1234, 1234567890, 987654321};
     std::string stored_str_value{ "00000" };
     for (auto& e : arrIntNums)
     {
          stored_str_value = "00000";
          std::cout << "Array element = " << e << std::endl;
          const auto res = std::to_chars(stored_str_value.data(), 
              stored_str_value.data() + stored_str_value.size(), e /*, int base = 10*/);

          switch (res.ec)
          {
               case std::errc():  
                    std::cout << "Stored value: " << stored_str_value << ", 
                    Number of characters = " << res.ptr - stored_str_value.data() << std::endl;
                    break;
               case std::errc::result_out_of_range:  
                    std::cout << "Result out of range! Number of characters = " 
                              << res.ptr - stored_str_value.data() << std::endl;
                    break;	
               case std::errc::value_too_large:
                    std::cout << "Value too large!" << std::endl;
                    break;
               default:  
                    std::cout << "Error: res.ec = " << int(res.ec) << std::endl;
          }

     }

     std::cout << "--------------------------------------------------------------------------------------------------------------------\n";
     std::cout << "Let's demonstrate the conversion of double values to a string (5 characters long) using the 'std::to_chars' function " << std::endl;
     std::cout << "--------------------------------------------------------------------------------------------------------------------\n";
     
     // construction uses aggregate initialization
     std::array<double, 8> arrDoubleNums = {4.02, 7e+5, 5, -67.90000, 
                                 10.9000000000000000000101,20.9e+0,-20.9e+1,-10.1};
     
     for (auto& e : arrDoubleNums)
     {
          stored_str_value = "00000";
          std::cout << "Array element = " << e << std::endl;
          const auto res = std::to_chars(stored_str_value.data(), 
          stored_str_value.data() + stored_str_value.size(), e, std::chars_format::general);

          switch (res.ec)
          {
               case std::errc():
                    std::cout << "Stored value: " << stored_str_value << ", 
                    Number of characters = " << res.ptr - stored_str_value.data() << std::endl;
                    break;
               case std::errc::result_out_of_range:
                    std::cout << "Result out of range! Number of characters = " 
                              << res.ptr - stored_str_value.data() << std::endl;
                    break;
               case std::errc::value_too_large:
                    std::cout << "Value too large!" << std::endl;
                    break;
               default:
                    std::cout << "Error: res.ec = " << int(res.ec) << std::endl;
          }
     }
     
     return 0;
}

看里面的代码拐来拐去,真是不想用,不过看性能提升这么明显,还是忍耐下吧。STL的风格就是尖括号多,函数多,不能直接看到指针。

友情链接
版权所有 Copyright(c)2004-2024 锐英源软件
统一社会信用代码:91410105098562502G 豫ICP备08007559号 最佳分辨率 1440*900
地址:郑州市金水区文化路97号郑州大学北区院内南门附近