📜  C++中的三法则(1)

📅  最后修改于: 2023-12-03 14:39:57.930000             🧑  作者: Mango

C++中的三法则

C++中的三法则是指 三个重要的规则,它们是 C++ 语言设计的基础。掌握这些法则,有助于我们写出更加健壮、安全的 C++ 代码。

一、析构函数中不要抛出异常

析构函数是在对象生命周期结束时被执行的函数,用于清理资源。如果在析构函数中抛出异常,会导致程序无法正常清理资源,可能会导致内存泄漏等问题。

以下是一个错误的示例:

class Test {
public:
    Test() {}

    ~Test() {
        throw std::exception("error");
    }
};

int main() {
    try {
        Test test;
    }
    catch (std::exception& e) {
        std::cout << e.what() << std::endl;
    }
    return 0;
}

上述代码中,当 Test 对象被销毁时抛出了异常,但是该异常会被 catch 语句捕获,导致我们无法定位错误。因此,我们应该避免在析构函数中抛出异常。

二、拷贝构造函数和赋值操作符需要正确实现

C++ 中的拷贝构造函数和赋值操作符用于将一个对象的值赋给另一个对象。如果我们没有正确实现这两个函数,可能会导致对象创建和销毁时的问题。

以下是一个错误的示例:

class Test {
public:
    Test() {
        m_data = new int[10];
    }

    ~Test() {
        delete[] m_data;
    }

    Test(const Test& other) {
        m_data = new int[10];
        m_data = other.m_data;
    }

    Test& operator=(const Test& other) {
        delete[] m_data;
        m_data = new int[10];
        m_data = other.m_data;
        return *this;
    }

private:
    int* m_data;
};

int main() {
    Test test1;
    Test test2 = test1;
    Test test3;
    test3 = test1;
    return 0;
}

上述代码中,Test 类有一个 new int[10] 的成员变量 m_data,在拷贝构造函数和赋值操作符中,我们只是简单地拷贝了指针而没有实现真正的拷贝。这会导致 m_data 的两个指针指向同一块内存,当其中一个对象被销毁时,也会导致另一个对象的数据被破坏。

我们应该正确实现拷贝构造函数和赋值操作符,例如:

class Test {
public:
    Test() {
        m_data = new int[10];
    }

    ~Test() {
        delete[] m_data;
    }

    Test(const Test& other) {
        m_data = new int[10];
        std::copy(other.m_data, other.m_data + 10, m_data);
    }

    Test& operator=(const Test& other) {
        if (this != &other) {
            delete[] m_data;
            m_data = new int[10];
            std::copy(other.m_data, other.m_data + 10, m_data);
        }
        return *this;
    }

private:
    int* m_data;
};

int main() {
    Test test1;
    Test test2 = test1;
    Test test3;
    test3 = test1;
    return 0;
}
三、内存泄漏需要避免

C++ 中,如果我们使用了 new 来动态分配内存,则一定要在适当的时间使用 deletedelete[] 来释放内存。否则会导致内存泄漏,最终会导致程序崩溃。

以下是一个错误的示例:

void func() {
    int* data = new int[10];
    // Do something
}

上述代码中,我们使用 new 来动态分配了内存,但是没有释放。这会导致内存泄漏。

我们应该在适当的时间使用 deletedelete[] 来释放内存,例如:

void func() {
    int* data = new int[10];
    // Do something
    delete[] data;
}
总结

C++ 中的三法则包括:析构函数中不要抛出异常、拷贝构造函数和赋值操作符需要正确实现、内存泄漏需要避免。掌握这些法则,有助于我们写出更加健壮、安全的 C++ 代码。