手记

C++高级语法资料详解与入门指南

本文详细介绍了C++高级语法中的模板、STL容器、智能指针、异常处理、多态以及内存管理等内容,帮助读者掌握C++编程的核心技巧。文章通过丰富的示例代码,阐述了如何使用这些高级特性来编写高效和健壮的C++程序。提供了全面的C++高级语法资料,旨在帮助编程者深入理解并应用这些高级特性。

C++高级语法详解与入门指南
C++模板基础

模板的基本概念

模板是C++中的一种强大特性,允许在编译时进行类型泛化和参数化。模板分为函数模板和类模板两种,它们允许我们编写通用的代码,然后根据具体的类型或参数实例化出特定的版本。

函数模板的使用

函数模板允许我们编写适应多种类型的函数。例如,编写一个通用的求最大值的函数模板:

template <typename T>
T max(const T& a, const T& b) {
    return (a > b) ? a : b;
}

int main() {
    int a = 10, b = 20;
    double c = 10.5, d = 20.5;
    std::cout << "Max of int: " << max(a, b) << std::endl;
    std::cout << "Max of double: " << max(c, d) << std::endl;
    return 0;
}

类模板的使用

类模板允许我们定义一个通用的数据结构,然后根据具体的类型实例化出特定的类。例如,定义一个通用的向量类:

template <typename T>
class Vector {
public:
    Vector(int size) : size(size), data(size, 0) {}
    void set(int index, const T& value) { data[index] = value; }
    T get(int index) const { return data[index]; }
private:
    int size;
    std::vector<T> data;
};

int main() {
    Vector<int> intVector(5);
    Vector<double> doubleVector(5);

    intVector.set(0, 10);
    doubleVector.set(0, 10.5);

    std::cout << "Int vector at index 0: " << intVector.get(0) << std::endl;
    std::cout << "Double vector at index 0: " << doubleVector.get(0) << std::endl;

    return 0;
}

模板特化

模板特化允许我们为特定的类型提供特定的实现。例如,为Vector<int>提供特化实现:

template <>
class Vector<int> {
public:
    Vector(int size) : size(size), data(size, 0) {}
    void set(int index, int value) { data[index] = value; }
    int get(int index) const { return data[index]; }
private:
    int size;
    std::vector<int> data;
};

int main() {
    Vector<int> intVector(5);
    intVector.set(0, 10);
    std::cout << "Int vector at index 0: " << intVector.get(0) << std::endl;

    return 0;
}
常用STL容器

向量(vector)的使用

vector是C++标准库中的一个动态数组容器,提供了在数组末尾动态添加或删除元素的能力。例如:

#include <vector>

int main() {
    std::vector<int> vec;
    vec.push_back(10);
    vec.push_back(20);
    vec.push_back(30);

    for (int i : vec) {
        std::cout << i << std::endl;
    }

    return 0;
}

列表(list)的使用

list是C++标准库中的一个双向链表容器,支持高效的插入和删除操作。例如:

#include <list>

int main() {
    std::list<int> lst;
    lst.push_back(10);
    lst.push_back(20);
    lst.push_back(30);

    for (int i : lst) {
        std::cout << i << std::endl;
    }

    return 0;
}

队列(queue)的使用

queue是C++标准库中的一个先进先出队列容器。例如:

#include <queue>

int main() {
    std::queue<int> q;
    q.push(10);
    q.push(20);
    q.push(30);

    while (!q.empty()) {
        std::cout << q.front() << std::endl;
        q.pop();
    }

    return 0;
}

栈(stack)的使用

stack是C++标准库中的一个后进先出栈容器。例如:

#include <stack>

int main() {
    std::stack<int> s;
    s.push(10);
    s.push(20);
    s.push(30);

    while (!s.empty()) {
        std::cout << s.top() << std::endl;
        s.pop();
    }

    return 0;
}
智能指针介绍

unique_ptr的基本用法

unique_ptr是C++11引入的一种独占所有权的智能指针,它确保一次只有一个智能指针拥有资源。例如:

#include <memory>

int main() {
    std::unique_ptr<int> ptr(new int(10));
    std::cout << *ptr << std::endl;

    // unique_ptr无法复制,只能移动
    // std::unique_ptr<int> ptr2 = ptr;
    std::unique_ptr<int> ptr2 = std::move(ptr);
    std::cout << *ptr2 << std::endl;

    return 0;
}

shared_ptr的基本用法

shared_ptr是一种共享所有权的智能指针,多个shared_ptr可以共同拥有资源。例如:

#include <memory>

int main() {
    std::shared_ptr<int> ptr(new int(10));
    std::cout << *ptr << std::endl;

    std::shared_ptr<int> ptr2 = ptr;
    std::cout << *ptr2 << std::endl;

    return 0;
}

weak_ptr的基本用法

weak_ptr是一种弱引用智能指针,它可以指向由shared_ptr管理的对象,但不增加引用计数。例如:

#include <memory>

int main() {
    std::shared_ptr<int> ptr(new int(10));
    std::weak_ptr<int> weakPtr = ptr;

    if (std::shared_ptr<int> ptr2 = weakPtr.lock()) {
        std::cout << *ptr2 << std::endl;
    } else {
        std::cout << "Weak pointer expired" << std::endl;
    }

    return 0;
}
C++异常处理

异常的基本概念

异常是一种在程序运行时发生的错误,程序可以捕捉并处理这些错误。异常处理的基本语法包括trycatchthrow

抛出异常的语法

使用throw关键字可以抛出异常,例如:

void throwException(int n) {
    if (n < 0) {
        throw std::runtime_error("Negative number not allowed");
    }
}

int main() {
    try {
        throwException(-10);
    } catch (const std::runtime_error& e) {
        std::cout << "Exception: " << e.what() << std::endl;
    }

    return 0;
}

捕获异常的语法

使用catch块来捕获异常,例如:

void throwException(int n) {
    if (n < 0) {
        throw std::runtime_error("Negative number not allowed");
    }
}

int main() {
    try {
        throwException(-10);
    } catch (const std::runtime_error& e) {
        std::cout << "Exception: " << e.what() << std::endl;
    }

    return 0;
}

异常处理的注意事项

  • 异常处理应尽可能简洁,不要在异常处理代码中进行复杂的资源释放或清理操作。例如,避免在catch块中执行耗时的逻辑。
  • 不要忽略捕获到的异常,这可能导致程序崩溃或进入不可恢复的状态。例如,确保每个异常都被适当处理。
  • 注意异常的传播,确保异常可以在适当的地方被捕获和处理。例如,确保try块覆盖所有可能抛出异常的代码。
静态与动态多态

静态多态的实现

静态多态通过泛型编程实现,例如函数模板或类模板。这类多态在编译时确定,不会在运行时改变。例如,使用函数模板实现静态多态:

template <typename T>
T sum(const T& a, const T& b) {
    return a + b;
}

int main() {
    int a = 10, b = 20;
    double c = 10.5, d = 20.5;
    std::cout << "Sum of int: " << sum(a, b) << std::endl;
    std::cout << "Sum of double: " << sum(c, d) << std::endl;

    return 0;
}

动态多态的实现

动态多态通过继承和虚函数实现,可以在运行时根据对象的实际类型调用不同的函数。例如:

class Base {
public:
    virtual void print() const {
        std::cout << "Base class print" << std::endl;
    }
};

class Derived : public Base {
public:
    void print() const override {
        std::cout << "Derived class print" << std::endl;
    }
};

int main() {
    Base base;
    Derived derived;

    Base& baseRef = base;
    Base& derivedRef = derived;

    baseRef.print();  // 输出: Base class print
    derivedRef.print();  // 输出: Derived class print

    return 0;
}

虚函数与纯虚函数

虚函数允许基类和派生类定义相同名称的方法,从而实现多态。纯虚函数是用于定义抽象类的虚函数,其在基类中没有实现,必须由派生类实现。

class Base {
public:
    virtual void print() const = 0;  // 纯虚函数
};

class Derived : public Base {
public:
    void print() const override {
        std::cout << "Derived class print" << std::endl;
    }
};

int main() {
    Derived derived;
    derived.print();  // 输出: Derived class print

    return 0;
}

抽象类的使用

抽象类是一种无法实例化的类,它们通常用于定义接口或基类。抽象类至少包含一个纯虚函数。

class AbstractClass {
public:
    virtual void print() const = 0;  // 纯虚函数
};

class ConcreteClass : public AbstractClass {
public:
    void print() const override {
        std::cout << "Concrete class print" << std::endl;
    }
};

int main() {
    ConcreteClass concrete;
    concrete.print();  // 输出: Concrete class print

    // AbstractClass abs;  // 编译错误:无法实例化抽象类
    return 0;
}
C++内存管理

堆与栈的区别

栈是自动管理的内存区域,用于存储局部变量和函数调用等;堆是动态分配的内存区域,用于存储动态分配的对象和数据结构。

int main() {
    int stackVar = 10;  // 存储在栈中
    int* heapVar = new int(10);  // 存储在堆中

    std::cout << "Stack variable: " << stackVar << std::endl;
    std::cout << "Heap variable: " << *heapVar << std::endl;

    delete heapVar;  // 释放堆内存
    return 0;
}

new与delete的使用

new用于在堆中分配内存,delete用于释放堆内存。例如:

int main() {
    int* ptr = new int(10);
    std::cout << "Value: " << *ptr << std::endl;

    delete ptr;
    ptr = nullptr;  // 防止悬挂指针

    return 0;
}

RAII技术介绍

RAII(Resource Acquisition Is Initialization)是一种内存管理技术,通过对象的生命周期管理资源。例如,使用智能指针unique_ptr实现RAII:

#include <memory>

class Resource {
public:
    Resource() {
        std::cout << "Resource allocated" << std::endl;
    }
    ~Resource() {
        std::cout << "Resource deallocated" << std::endl;
    }
};

int main() {
    {
        std::unique_ptr<Resource> resource(new Resource());
        // 资源在离开作用域时自动释放
    }

    return 0;
}

通过这种方式,资源的管理与对象的生命周期绑定,避免了内存泄漏和资源管理的复杂性。

总结,C++高级语法包括模板、STL容器、智能指针、异常处理、多态和内存管理等,这些特性使得C++成为一种强大且灵活的编程语言。通过深入理解这些特性,可以编写出高效且健壮的C++程序。

0人推荐
随时随地看视频
慕课网APP