c ++函数功能查询器_C ++ 17新功能和技巧

本文详细介绍了C++17的新特性,包括结构绑定、带有初始化程序的'if'和'switch'语句、constexpr lambdas、std::string_view、并行算法等。通过实例展示了如何在实践中应用这些新功能,帮助读者更好地理解和利用C++17的更新,以提高代码的可读性、表达力和性能。
摘要由CSDN通过智能技术生成

c ++函数功能查询器

目录 (Table of Contents)

介绍 (Introduction)

In this article, we will talk about the new features of the new C++17 standard.

在本文中,我们将讨论新的C ++ 17标准的新功能。

The article presents real examples that will help a beginner in the new standard of the language to understand faster how to apply new features in practice.

本文提供了真实的示例,这些示例将帮助使用该语言新标准的初学者更快地了解如何在实践中应用新功能。

The code in the sections was tested in Visual Studio 2017.

本节中的代码已在Visual Studio 2017中进行了测试。

(You can click on the image to view the enlarged, original image here.)

(您可以单击图像在此处查看放大的原始图像。)

设置集成开发环境(IDE) (Settings an Integrated Development Environment (IDE))

Regardless of the IDE, you will most likely have to configure it to work with the latest C ++ standard.

无论使用哪种IDE,您都极有可能必须对其进行配置以使其与最新的C ++标准兼容。

I work with Visual Studio 2017, so I’ll show you how to set it up to work with the new standard:

我使用Visual Studio 2017,因此我将向您展示如何设置它以与新标准一起使用:

设置C ++版本 (Set C++ Version)

To set on compiler option for the Visual Studio project, follow these steps:

要为Visual Studio项目设置编译器选项,请按照下列步骤操作:

  1. In the Solution Explorer window, right-click the project name, and then choose Properties to open the project Property Pages dialog (or press ALT + ENTER).

    在“解决方案资源管理器”窗口中,右键单击项目名称,然后选择“属性”以打开项目的“属性页”对话框(或按ALT + ENTER键)。
  2. Select the Configuration properties > C/C++ > Language property page.

    选择配置属性> C / C ++>语言属性页面。
  3. In the property list, select the drop-down for the "Conformance mode" property, and then choose /permissive.

    在属性列表中,选择“ 一致性模式 ”属性的下拉列表,然后选择/ permissive

    It will disable non-standard C++ extensions and will enable standard conformance in VS2017.

    它将禁用非标准C ++扩展,并在VS2017中启用标准一致性。

  4. In the property list, select the drop-down for the "C++ Language Standard" property, and then choose /std:c++17 or /std:c++latest.

    在属性列表中,选择“ C ++语言标准 ”属性的下拉列表,然后选择/ std:c ++ 17/ std:c ++ latest

  5. Press the "OK" button to save your changes.

    按“ 确定 ”按钮保存更改。

Simple copying

To enable the latest features of the new standard, you can also take a different approach:

要启用新标准的最新功能,您还可以采用其他方法:

  1. Open the project's Property Pages dialog box.

    打开项目的“属性页”对话框。
  2. Select "Configuration Properties"-> "C/C++"->"Command Line".

    选择“ 配置属性 ”->“ C / C ++ ”->“ 命令行 ”。

  3. Add to "Additional Options" textbox following param: /std:c++17 or /std:c++latest

    在参数后添加到“ 其他选项 ”文本框: / std:c ++ 17/ std:c ++ latest

  4. Press the "OK" button to save your changes.

    按“ 确定 ”按钮保存更改。

Simple copying

结构绑定 (Structure Binding)

Multiple return values from functions are not a new concept in programming and similar functionality is present in many other programming languages. C++17 comes with a new feature (structured bindings) that provides functionality similar to the multiple return values provided in other languages.

函数的多个返回值并不是编程中的新概念,并且许多其他编程语言中也存在类似的功能。 C ++ 17带有一项新功能(结构化绑定),其功能类似于其他语言提供的多个返回值。

In the following example, I want to provide an overview of some of the options that we have in the old C++ standard, in the modern standard (C++11/14) and today in C++17 to return multiple values from functions:

在下面的示例中,我想概述一下旧的C ++标准,现代的标准(C ++ 11/14)和今天的C ++ 17中从函数返回多个值的一些选项。 :

  1  #include <iostream>
  2  #include <tuple> // std::tie
  3  
  4  const double PI = 3.14159265;
  5  
  6  void calculateSinCos(const double param, double & resSin, double & resCos)
  7  {
  8       resSin = sin(param * PI / 180.0); // converting degrees to radians
  9       resCos = cos(param * PI / 180.0); // converting degrees to radians
 10  }
 11  
 12  std::pair<double, double> calculateSinCos(const double param)
 13  {
 14       return { sin(param * PI / 180.0), cos(param * PI / 180.0) };
 15  }
 16  
 17  std::tuple<double, double> calculateSinCos_Tuple(const double param)
 18  {
 19       return std::make_tuple(sin(param * PI / 180.0),
 20              cos(param * PI / 180.0));  // packing values into tuple
 21  }
 22  
 23  int main()
 24  {
 25       double param { 90.0 };
 26       double resultSin { 0.0 };
 27       double resultCos { 0.0 };
 28  
 29       //C++98
 30       calculateSinCos(param, resultSin, resultCos);
 31       std::cout << "C++98 : sin(" << param << ") = " <<
 32       resultSin << ", cos(" << param << ") = "
 33       << resultCos << "\n";
 34  
 35       //C++11
 36       const auto resSinCos(calculateSinCos(param));
 37       std::cout << "C++11 : sin(" << param << ") = " <<
 38       resSinCos.first << ", cos(" << param << ") = "
 39       << resSinCos.second << "\n";
 40  
 41       //C++11
 42       std::tie(resultSin, resultCos) = calculateSinCos(param);
 43       std::cout << "C++11 : sin(" << param << ") = " <<
 44       resultSin << ", cos(" << param << ") = "
 45       << resultCos << "\n";
 46  
 47       // C++17
 48       auto[a, b] =  calculateSinCos(param);
 49       std::cout << "C++17 :
 50       sin(" << param << ") = " << a << ",
 51       cos(" << param << ") = " << b << "\n";
 52  
 53       // C++17
 54       auto[x, y] =
 55          calculateSinCos_Tuple(param); // std::make_tuple(sin(val), cos(val));
 56       std::cout << "C++17 :
 57       sin(" << param << ") = " << x << ",
 58       cos(" << param << ") = " << y << "\n";
 59  }


Let's look at the above code:

让我们看一下上面的代码:

  1. In this approach:

    在这种方法中:

    calculateSinCos(param, resultSin, resultCos);
    
    	

    we used the oldest and possibly still most common method - using the OUTPUT params passed as reference can be used to "return" values to the caller.

    我们使用了最古老且可能仍是最常见的方法-使用作为参考传递的OUTPUT参数可以将值“返回”给调用者。

  2. Consider the different way to access multiple values returned from functions:

    考虑访问从函数返回的多个值的不同方法:

    const auto resSinCos(calculateSinCos(param));
    
    	

    Accessing the individual values of the resulting std::pair by resSinCos.first and resSinCos.second was not very expressive, since we can easily confuse the names, and it’s hard to read.

    通过resSinCos.firstresSinCos.second访问生成的std::pair的各个值并不是很容易表达,因为我们很容易混淆名称,而且很难阅读。

  3. Alternatively, before C++17, it would be possible to use std::tie to unpack a tuple/pair to achieve a similar effect:

    或者,在C ++ 17之前,可以使用std::tie解开一个元组/对,以达到类似的效果:

    std::tie(resultSin, resultCos) = calculateSinCos(param);
    
    	

    This approach demonstrates how to unpack the resulting pair into two variables. Notice, this example shows all the power of std::tie, but nonetheless, the std::tie is less powerful than structured bindings, because we must first define all the variables we want to bind.

    该方法演示了如何将结果对分解为两个变量。 注意,此示例显示了std::tie所有功能,但是std::tie的功能不如结构化绑定,因为我们必须首先定义要绑定的所有变量。

  4. Structured binding is a new functionality of C++17, making the code even more readable, expressive and concise.

    结构化绑定是C ++ 17的一项新功能 ,使代码更具可读性,表达力和简洁性。

    auto[a, b] = calculateSinCos(param);
    
    	

    Notice, the variables a and b are not references; they are aliases (or bindings) to the generated object member variables. The compiler assigns a unique name to the temporary object.

    注意,变量ab不是引用; 它们是生成的对象成员变量的别名(或绑定)。 编译器为临时对象分配一个唯一的名称。

  5. In C++11, the std::tuple container has been added to build a tuple that contains multiple return values. But neither C++11 nor C++14 does support an easy way to get elements in a std::tuple directly from the tuple (Of course, we can unpack a tuple using std::tie, but we still need to understand the type of each object and how many objects are this tuple. Phew, how painful it is...)

    在C ++ 11中,已添加std::tuple容器以构建包含多个返回值的元组。 但是C ++ 11和C ++ 14都不支持直接从元组中获取std::tuple元素的简单方法(当然,我们可以使用std::tie解开元组的std::tie ,但是我们仍然需要了解每个对象的类型以及该元组有多少个对象。Ph,这是多么痛苦...)

    C++17 fixes this flaw, and the structured bindings allow us to write code as follows:

    C ++ 17修复了此缺陷,结构化绑定使我们可以编写如下代码

    auto[x, y] = calculateSinCos_Tuple(param);
    	

Let's see the output of the above code of structure binding:

让我们看一下上面的结构绑定代码的输出:

As we can see, different approaches show the same result....

我们可以看到,不同的方法显示出相同的结果。

带有初始化程序的“ if”和“ switch”语句 ('if' and 'switch' Statements with Initializers)

Good programming style limits the scope of variables. Sometimes, it is required to get some value, and only if it meets a certain condition can it be processed further.

好的编程风格会限制变量的范围。 有时,需要获得一定的价值,并且只有在满足特定条件的情况下,才能对其进行进一步处理。

For this purpose, C++17 provides a new version of the 'if' statement with initializer.

为此,C ++ 17提供了带有初始化程序的' if '语句的新版本。

if (init; condition)


Let's see how the 'if' condition worked before the new C++17 standard:

让我们看看' if '条件在新的C ++ 17标准之前如何工作:

#include <iostream>

int getValueOfNumber() {

	return 5;
}

int main() {
 
	int num = getValueOfNumber();
	if (num > 100) {
		std::cout << "The value of the num is greater than 100" << std::endl;
	}	
	else {
		std::cout << "The value of the num is less than or equal to 100" << std::endl;
	}
	
	std::cout << "num =" << num << std::endl;
}

Please notice that the num value is visible inside the if and else statements, as well as OUTSIDE the scope conditions.

请注意, num值在ifelse语句以及范围条件之外均可见。

Now, in C++17, we can write:

现在,在C ++ 17中,我们可以编写:

#include <iostream>

int getValueOfNumber() {

     return 5;
}

int main() {

	if (auto num = getValueOfNumber(); num > 100) {
		std::cout << "The value of the num is greater than 100" << std::endl;
	}
	else {
		std::cout << "The value of the num is less than or equal to 100" << std::endl;
	}

	std::cout << "num =" << num;
}

If we try to compile the above code, we will get the following error:

如果我们尝试编译以上代码,则会收到以下错误:

Error

Now, num is visible only INSIDE the if and else statements, so accessing a variable outside the scope of if/else causes an error...

现在, num仅在ifelse语句内部可见,因此访问if / else范围之外的变量会导致错误...

The same applies to switch statements.

这同样适用于switch语句。

C++17 provides new version of the 'switch' statement with initializers.

C ++ 17提供了带有初始化程序的新版本的' switch '语句。

switch (init; condition)


Let's see how the 'switch' condition worked before the new C++17 standard:

让我们看看在新的C ++ 17标准之前' switch '条件是如何工作的:

#include <iostream>
#include <cstdlib>
#include <ctime>
     
int getRandomValueBetween_1_and_2() {
     srand(time(NULL));
     return rand() % 2 + 1; // // value in the range 1 to 2
}

int main() {
     
     int num = getRandomValueBetween_1_and_2();
     switch (num) {
     case 1: 
          std::cout << "num = 1 \n"; break;
     case 2: 
          std::cout << "num = 2 \n"; break;
     default: 
          std::cout << "Error value in num ! \n";
     }
     
     std::cout << "Value output outside the 'switch': num =" << num << std::endl;
}

Please notice that the num value is visible inside the switch statements, as well as OUTSIDE the scope conditions.

请注意, num值在switch语句内部以及范围条件之外均可见。

Now, in C++17, we can write:

现在,在C ++ 17中,我们可以编写:

#include <iostream>
#include <cstdlib>
#include <ctime>
     
int getRandomValueBetween_1_and_2() {
     srand(time(NULL));
     return rand() % 2 + 1; // value in the range 1 to 2
}

int main() {
     
     switch (auto num(getRandomValueBetween_1_and_2()); num) {
     case 1:
          std::cout << "num = 1 \n"; break;
     case 2:
          std::cout << "num = 2 \n"; break;
     default:
          std::cout << "Error value in num ! \n";
     }

     std::cout << "Value output outside the 'switch': num =" << num << std::endl;
}

If we try to compile the above code, we will get the following error:

如果我们尝试编译以上代码,则会收到以下错误:

Error

Now, num is visible only INSIDE the switch statements, so accessing a variable outside the scope of switch causes an error...

现在,num仅在switch语句内部可见,因此访问switch范围之外的变量会导致错误...

Due to the described mechanism, the scope of the variable remains short. Before C++17, this could only be achieved with additional {curly braces}.

由于所描述的机制,该变量的范围仍然很短。 在C ++ 17之前,只能通过附加的{curly braces}来实现。

The short lifetimes reduce the number of variables in scope, keeping code clean and making refactoring easier.

较短的生命周期减少了作用域中的变量数量,从而保持了代码的整洁并使重构更加容易。

Thus, this new C++17 feature is very useful for further use.

因此,此新的C ++ 17功能对于进一步使用非常有用。

Constexpr Lambdas和捕获* this by Value (Constexpr Lambdas and Capturing *this by Value)

As it is written here: "In C++11 and later, a lambda expression—often called a lambda—is a convenient way of defining an anonymous function object (a closure) right at the location where it is invoked or passed as an argument to a function. Typically, lambdas are used to encapsulate a few lines of code that are passed to algorithms or asynchronous methods. This article defines what lambdas are, compares them to other programming techniques, describes their advantages, and provides a basic example."

就像这里写的那样:“在C ++ 11和更高版本中,lambda表达式(通常称为lambda)是一种在调用或传递匿名函数对象(即闭包)的位置处定义匿名函数对象(闭包)的便捷方法。通常,lambda用于封装传递给算法或异步方法的几行代码本文定义了lambda,将其与其他编程技术进行比较,描述它们的优势,并提供一个基本示例。 ”

C++17 offers two significant improvements to lambda expressions:

C ++ 17对lambda表达式进行了两项重大改进:

  • constexpr lambdas

    constexpr lambdas

  • capture of *this

    捕获* this

constexpr lambdas (constexpr lambdas)

Lambda expressions are a short form for writing anonymous functors introduced in C++11, which have become an integral part of modern C++ standard. Using the constexpr keyword, also introduced in C++11, we can evaluate the value of a function or variable at compile time. In C++17, these two entities are allowed to interact together, so lambda can be invoked in the context of a constant expression.

Lambda表达式是编写C ++ 11中引入的匿名函子的一种简短形式,匿名函子已成为现代C ++标准不可或缺的一部分。 使用也在C ++ 11中引入的constexpr关键字,我们可以在编译时评估函数或变量的值。 在C ++ 17中,允许这两个实体一起交互,因此可以在常量表达式的上下文中调用lambda。

For example:

例如:

constexpr auto my_val {foo()};


Declaring the variable my_val with the constexpr modifier will ensure that the function object it stores will be created and initialized at compile time.

使用constexpr修饰符声明变量my_val将确保在编译时创建并初始化存储的函数对象。

In the definition of a lambda expression, we can use the optional constexpr parameter:

lambda表达式定义中,我们可以使用可选的constexpr参数:

[capture clause] (parameter list) mutable costexpr exception-specification -> return-type
{

}

If we explicitly mark the lambda expression with the constexpr keyword, then the compiler will generate an error when this expression does not meet the criteria of the constexpr function. The advantage of using constexpr functions and lambda expressions is that the compiler can evaluate their result at compile time if they are called with parameters that are constant throughout the process. This will result in less code in the binary later. If we do not explicitly indicate that lambda expressions are constexpr, but these expressions meet all the required criteria, then they will be considered constexpr anyway, only implicitly.

如果我们用constexpr关键字显式标记lambda表达式,则当该表达式不符合constexpr函数的条件时,编译器将生成错误。 使用constexpr函数和lambda表达式的优点是,如果在整个过程中使用不变的参数调用它们,则编译器可以在编译时评估其结果。 稍后将减少二进制代码的数量。 如果我们没有明确指出lambda表达式是constexpr ,但是这些表达式满足所有必需的条件,则无论如何,它们都将被视为constexpr ,只是隐式地。

For example:

例如:

constexpr auto NvalueLambda = [](int n) { return n; };   // implicitly constexpr


If we want the lambda expression to be constexpr, then it is better to explicitly set it as such, because in case of errors the compiler will help us identify them by printing error messages.

如果我们希望lambda表达式为constexpr ,则最好将其设置为这样,因为在发生错误的情况下,编译器将通过打印错误消息来帮助我们识别它们。

Let's look at an example demonstrating how C++17 evaluates statically (at compile time) lambda expressions and functions:

让我们看一个示例,该示例演示C ++ 17如何静态(在编译时)评估lambda表达式和函数:

#include <iostream>
 
constexpr int Increment(int value) {
	return [value] 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值