C++高级特性与智能指针应用
立即解锁
发布时间: 2025-08-20 01:48:58 阅读量: 1 订阅数: 3 


懒惰程序员的C++入门指南
### C++高级特性与智能指针应用
#### 1. Lambda函数的使用
Lambda函数在C++中是一种匿名函数,它可以捕获外部变量,为代码编写提供了很大的灵活性。下面是一个使用值捕获的Lambda函数示例,用于检查“Los Angeles”中是否包含字母 'x':
```cpp
char badLetter = 'x';
assert(find_if(LA.name().begin(), LA.name().end(),
[badLetter](char ch) { return ch == badLetter; })
== LA.name().end());
```
此外,还给出了一些使用Lambda函数的练习:
1. 使用`for_each`函数将字符串容器中的每个元素大写。
2. 使用`count_if`函数统计容器中整数是整数平方的个数。
3. 使用`all_of`函数验证容器中的每个字符串是否包含用户给定的子字符串。
4. 按纬度对`City`对象进行排序。
#### 2. 结构化绑定和元组:一次性返回多个值
在C++中,函数通常只能返回一个值,但通过使用元组(tuple)和结构化绑定,我们可以轻松地一次性返回多个值。具体步骤如下:
1. **包含头文件**:`#include <tuple>`,元组是一个值序列,可能包含不同类型的值。
2. **函数返回类型**:让函数返回`auto`,编译器会自动推断返回的是`std::tuple<firstType,secondType,...>`类型。
3. **返回值**:使用`return std::make_tuple (value1, value2, ...);`返回多个值。
4. **存储返回值**:使用结构化绑定`auto [variable1, variable2, ...] = functionCall (...);`来存储返回的值。
5. **指定C++标准**:在编写代码时,需要告诉编译器使用C++17标准。
以下是一个计算二次方程根的示例:
```cpp
#include <iostream>
#include <cmath> //for sqrt
#include <tuple> //for tuple stuff
#include <cassert>
using namespace std;
auto quadraticFormula(double a, double b, double c)
{
int numroots = 0;
double root1 = 0.0;
double root2 = 0.0;
double underTheRadical = b * b - 4 * a*c;
if (underTheRadical >= 0)
{
root1 = (-b + sqrt(underTheRadical)) / (2 * a);
root2 = (-b - sqrt(underTheRadical)) / (2 * a);
if (root1 == root2) numroots = 1; else numroots = 2;
}
return std::make_tuple(numroots, root1, root2);
}
int main ()
{
cout << "Enter the a, b, c from ax^2+bx+c = 0: ";
double a, b, c; cin >> a >> b >> c;
auto[howMany, r1, r2] = quadraticFormula(a, b, c);
switch (howMany)
{
case 0: cout << "No solution.\n"; break;
case 1: cout << "Solution is " <<r1<<endl; break;
case 2: cout << "Solutions are " <<r1<<' '<<r2<<endl; break;
default:cout << "Can't have " <<howMany<<" solutions!\n";
}
return 0;
}
```
基于此,更新了函数参数和返回值的黄金规则:
| 情况 | 处理方式 |
| ---- | ---- |
| 函数提供小值 | 直接返回;若为多个值,返回元组 |
| 函数提供大值 | 通过引用传递 |
| 函数修改传入变量 | 通过引用传递 |
| 函数不修改传入变量 | 若为对象,以`const TheClass& object`传递;否则按值传递 |
| 移动构造或移动赋值 | 通过右值引用传递 |
元组还可以在其他地方使用,通过`std::get<>()`来访问元组的元素,例如:
```cpp
std::tuple<int, double, double> myTuple = std::make_tuple(0, 2.0, 3.0);
assert(std::get<0>(myTuple) == 0);
std::get<0>(myTuple) = 1;
```
同时,也给出了一些关于元组的练习:
1. 编写一个`sortedTriple`函数,对包含三个元素的元组进行排序并返回新的元组。
2. 编写一个函数,对于给定的向量,返回其最大值、最小值、平均值和标准差,结果存储在元组中;再编写一个对列表做相同操作的函数。
#### 3. 智能指针
C++的更新旨在减少指针错误对代码的影响,智能指针是其中的重要改进。
##### 3.1 unique_ptr
`std::unique_ptr`是一个主要的智能指针,它管理一个指针,允许使用该指针,并在其超出作用域时自动删除它。通常使用`make_unique`进行初始化,示例如下:
```cpp
#include <memory>
std::unique_ptr<int> p1 = std::make_unique<int>(27);
std::unique_ptr<Date> pDate = std::make_unique<Date>(1, 1, 2000);
std::unique_ptr<char[]> myChars = std::make_unique<char[]>(100);
```
使用`unique_ptr`的好处包括:
- **错误预防**:避免忘记初始化或删除指针,并且当指针被删除后,它会自动设置为`nullptr`,防止误使用。
- **异常安全**:当函数退出时,`unique_ptr`会自动调用析构函数,释放内存,避免内存泄漏。
以下是一个使用`unique_ptr`的奥林匹克符号程序示例:
```cpp
#include <vector>
#include <memory>
#include "circle.h"
#include "text.h"
int main (int argc, char** argv)
{
SSDL_SetWindowSize (500, 300);
std::vector<std::unique_ptr<Shape>> olympicSymbol;
enum {RADIUS = 50};
olympicSymbol.push_back(std::make_unique<Circle>( 50, 50, RADIUS));
olympicSymbol.push_back(std::make_unique<Circle>(150, 50, RADIUS));
olympicSymbol.push_back(std::make_unique<Circle>(250, 50, RADIUS));
olympicSymbol.push_back(std::make_unique<Circle>(100, 100, RADIUS));
olympicSymbol.push_back(std::make_unique<Circle>(200, 100, RADIUS));
olympicSymbol.push_back(std::make_unique<Text>(150,150,"Games of the Olympiad"));
SSDL_Color olympicColors = { BLUE,
SSDL_CreateColor (0, 255, 255) /*yellow*/,
```
0
0
复制全文
相关推荐










