大二上 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循环是一种非常有用的工具,它使得遍历容器变得简单且代码更加清晰。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~