大二上 C++程序设计笔记:终止程序函数abort与exit与lower_bound函数 智能指针与基于范围的for用法 20241104
1.abort和exit函数的用法
在C++中,abort() 和 exit() 都是用来终止程序执行的函数,但它们的用途和行为有所不同。
abort() 函数
abort() 函数是定义在 <cstdlib> 或 <stdlib.h> 头文件中的,它用于异常终止程序。当调用 abort() 时,程序会立即停止执行,并且会进行堆栈展开(unwind),以调用所有已注册的析构函数和清理函数。然后,程序会向操作系统返回一个失败的状态码(通常是非零值),表明程序是非正常终止的。
示例代码:
#include <cstdlib>
#include <iostream>
int main() {
std::cout << "Program is running..." << std::endl;
abort(); // 调用 abort() 终止程序
std::cout << "This line will not be executed." << std::endl;
return 0; // 这行代码也不会被执行
}
在这个例子中,程序会在输出 "Program is running..." 后立即终止,不会执行后面的代码。
exit() 函数
exit() 函数也是定义在 <cstdlib> 或 <stdlib.h> 头文件中的,它用于正常终止程序。与 abort() 不同,exit() 允许程序在退出前执行一些清理工作,比如关闭文件、释放资源等。exit() 函数接受一个整型参数,这个参数会被用作程序的退出状态码。按照惯例,0 表示成功退出,非0值表示有错误或异常退出。
示例代码:
#include <cstdlib>
#include <iostream>
int main() {
std::cout << "Program is running..." << std::endl;
std::cout << "Program is about to exit..." << std::endl;
exit(0); // 调用 exit(0) 正常终止程序
std::cout << "This line will not be executed." << std::endl;
return 0; // 这行代码也不会被执行
}
在这个例子中,程序会在输出 "Program is about to exit..." 后正常终止,并且会返回状态码0。
总结
abort()用于异常终止程序,不进行清理工作,通常用于遇到严重错误时。exit()用于正常终止程序,允许进行清理工作,通常用于程序执行完毕后或者需要优雅地退出时。
在实际编程中,应该根据具体情况选择合适的函数来终止程序。
2.lower_bound函数的用法
lower_bound 是 C++ 标准库中的一个函数模板,定义在 <algorithm> 头文件中。它用于在已排序的容器中查找第一个不小于给定值的元素的位置。这个函数模板可以与任何支持随机访问迭代器的容器一起使用,比如数组、std::vector、std::deque、std::list 等。
函数原型
ForwardIterator lower_bound(ForwardIterator first,
ForwardIterator last,
const T& value);
ForwardIterator lower_bound(ForwardIterator first,
ForwardIterator last,
const T& value,
Compare comp);
first和last:定义了要搜索的容器的范围。value:是要查找的值。comp:是一个可选的比较函数或函数对象,它接受两个参数并返回一个布尔值,指示第一个参数是否被认为小于第二个参数。
行为
lower_bound 函数在 [first, last) 范围内执行二分查找,以找到第一个不小于 value 的元素的位置。如果 comp 被提供,则使用它来比较元素;否则,使用容器的比较运算符(通常是 operator<)。
返回值
返回的是一个迭代器,指向在排序范围内第一个不小于 value 的元素。如果所有元素都小于 value,则返回 last。
示例
#include <algorithm>
#include <vector>
#include <iostream>
int main() {
std::vector<int> data = {1, 2, 4, 4, 5, 6, 8};
int valueToFind = 4;
auto lower = std::lower_bound(data.begin(), data.end(), valueToFind);
if (lower != data.end()) {
std::cout << "The lower bound for " << valueToFind << " is at index: "
<< (lower - data.begin()) << std::endl;
} else {
std::cout << "The value " << valueToFind << " is not present in the data." << std::endl;
}
return 0;
}
在这个例子中,lower_bound 用于在向量 data 中查找第一个不小于 4 的元素的位置。输出将是该元素的索引。
lower_bound 是一个非常有用的函数,特别是在处理有序数据时,可以快速找到插入点或进行范围查询。
3.C++中的智能指针
智能指针是C++中提供的一种自动管理动态分配内存的机制,它们在对象不再使用时自动释放内存,从而帮助防止内存泄漏。智能指针是模板类,位于<memory>头文件中。C++标准库提供了几种智能指针,最常见的有:
std::unique_ptr:表示独占所有权的智能指针,一个对象在同一时间只能被一个std::unique_ptr拥有。std::shared_ptr:表示共享所有权的智能指针,多个std::shared_ptr可以指向同一个对象,对象会在最后一个指向它的智能指针销毁时被删除。std::weak_ptr:是一种不控制对象生命周期的智能指针,通常与std::shared_ptr配合使用,用于解决std::shared_ptr相互引用时可能产生的循环引用问题。
std::unique_ptr 示例
#include <memory>
#include <iostream>
class MyClass {
public:
MyClass() { std::cout << "MyClass created" << std::endl; }
~MyClass() { std::cout << "MyClass destroyed" << std::endl; }
};
int main() {
std::unique_ptr<MyClass> ptr(new MyClass()); // 创建智能指针并分配内存
// 不需要手动delete,离开作用域时自动释放内存
return 0;
}
在这个例子中,std::unique_ptr 管理了一个 MyClass 对象的生命周期。当 main 函数结束时,ptr 离开作用域并被销毁,MyClass 的实例也会自动被删除。
std::shared_ptr 示例
#include <memory>
#include <iostream>
class MyClass {
public:
MyClass() { std::cout << "MyClass created" << std::endl; }
~MyClass() { std::cout << "MyClass destroyed" << std::endl; }
};
int main() {
{
std::shared_ptr<MyClass> ptr1(new MyClass());
std::shared_ptr<MyClass> ptr2 = ptr1; // 共享同一个对象
// 两个智能指针都离开作用域,但对象不会被删除,因为引用计数为2
} // ptr1 和 ptr2 都离开作用域,引用计数减为0,对象被删除
return 0;
}
在这个例子中,ptr1 和 ptr2 都指向同一个 MyClass 对象。当它们离开作用域时,由于引用计数机制,对象不会被立即删除,直到所有指向该对象的 std::shared_ptr 都离开了作用域,引用计数减到0,对象才会被删除。
std::weak_ptr 示例
#include <memory>
#include <iostream>
class MyClass {
public:
std::weak_ptr<MyClass> weakThis;
MyClass() { weakThis = std::weak_ptr<MyClass>(shared_from_this()); }
~MyClass() { std::cout << "MyClass destroyed" << std::endl; }
};
int main() {
std::shared_ptr<MyClass> ptr1(new MyClass());
std::weak_ptr<MyClass> weakPtr = ptr1;
std::shared_ptr<MyClass> ptr2 = weakPtr.lock(); // 尝试从弱指针获取强指针
if (ptr2) {
std::cout << "MyClass is still alive" << std::endl;
} else {
std::cout << "MyClass has been destroyed" << std::endl;
}
// ptr1 离开作用域,对象被删除
return 0;
}
在这个例子中,weakPtr 是一个 std::weak_ptr,它不增加对象的引用计数。通过调用 lock() 方法,尝试从 weakPtr 获取一个 std::shared_ptr。如果对象仍然存在,lock() 方法会返回一个有效的 std::shared_ptr;如果对象已经被删除,它会返回一个空的 std::shared_ptr。
智能指针的使用可以减少内存泄漏的风险,但它们也有性能开销,因此在使用时需要根据实际情况权衡。
4.基于范围的for怎么用
基于范围的for循环(Range-based for loop)是C++11引入的一种简洁的循环结构,用于遍历容器(如数组、向量、列表等)中的所有元素。它的语法简单,可以减少代码量,并且提高代码的可读性。
基本语法
for (declaration : expression) {
// loop body
}
declaration:定义循环变量的类型和名称。expression:一个容器或者任何可以被解引用的对象。
示例
1. 遍历数组
#include <iostream>
int main() {
int arr[] = {1, 2, 3, 4, 5};
for (int num : arr) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
在这个例子中,num 是循环变量,它会依次取数组 arr 中的每个元素的值。
2. 遍历向量(Vector)
#include <iostream>
#include <vector>
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};
for (int num : vec) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
这里,vec 是一个 std::vector<int> 类型的容器,num 会遍历向量中的所有元素。
3. 遍历字符串
#include <iostream>
#include <string>
int main() {
std::string str = "Hello";
for (char ch : str) {
std::cout << ch << " ";
}
std::cout << std::endl;
return 0;
}
在这个例子中,ch 会遍历字符串 str 中的每个字符。
4. 遍历自定义容器
基于范围的for循环不仅限于标准库容器,也可以用于自定义容器,只要它们支持迭代器。
#include <iostream>
#include <list>
class MyContainer {
std::list<int> data;
public:
MyContainer(std::initializer_list<int> list) : data(list) {}
auto begin() { return data.begin(); }
auto end() { return data.end(); }
};
int main() {
MyContainer container = {1, 2, 3, 4, 5};
for (int num : container) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
在这个例子中,MyContainer 类提供了 begin() 和 end() 方法,使得它可以使用基于范围的for循环。
基于范围的for循环是一种非常有用的工具,它使得遍历容器变得简单且代码更加清晰。

浙公网安备 33010602011771号