大二上 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::vectorstd::dequestd::list 等。

函数原型

ForwardIterator lower_bound(ForwardIterator first,
                           ForwardIterator last,
                           const T& value);
ForwardIterator lower_bound(ForwardIterator first,
                           ForwardIterator last,
                           const T& value,
                           Compare comp);
  • firstlast:定义了要搜索的容器的范围。
  • 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++标准库提供了几种智能指针,最常见的有:

  1. std::unique_ptr:表示独占所有权的智能指针,一个对象在同一时间只能被一个std::unique_ptr拥有。
  2. std::shared_ptr:表示共享所有权的智能指针,多个std::shared_ptr可以指向同一个对象,对象会在最后一个指向它的智能指针销毁时被删除。
  3. 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;
}

在这个例子中,ptr1ptr2 都指向同一个 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循环是一种非常有用的工具,它使得遍历容器变得简单且代码更加清晰。

posted @   陆舟LandBoat  阅读(209)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~
点击右上角即可分享
微信分享提示