C++ 面试题 目录

C++ 中 “Rule of Three/Five/Zero” 的含义是什么?

推荐答案

在C++中,"Rule of Three/Five/Zero" 是关于资源管理的规则,主要涉及类的拷贝构造函数、拷贝赋值运算符和析构函数的实现。

  • Rule of Three: 如果一个类需要显式定义析构函数、拷贝构造函数或拷贝赋值运算符中的任何一个,那么它通常需要显式定义所有这三个函数。

  • Rule of Five: 在C++11及以后的版本中,除了Rule of Three中的三个函数外,还需要考虑移动构造函数和移动赋值运算符。因此,如果一个类需要显式定义析构函数、拷贝构造函数、拷贝赋值运算符、移动构造函数或移动赋值运算符中的任何一个,那么它通常需要显式定义所有这五个函数。

  • Rule of Zero: 如果一个类不需要管理任何资源(即不需要自定义析构函数、拷贝/移动构造函数或拷贝/移动赋值运算符),那么它应该遵循Rule of Zero,即不需要显式定义这些函数,而是依赖编译器生成的默认行为。

本题详细解读

Rule of Three

在C++中,如果一个类管理动态内存或其他资源,通常需要自定义析构函数来释放这些资源。如果类中有指针成员指向动态分配的内存,编译器生成的默认拷贝构造函数和拷贝赋值运算符只会进行浅拷贝,这可能导致多个对象共享同一块内存,从而在析构时引发双重释放问题。因此,需要自定义拷贝构造函数和拷贝赋值运算符来实现深拷贝。

-- -------------------- ---- -------
----- ------- -
-------
    --------- - -------- ------- --
    ---------- - ------ ----- -  -- -------

    -- ---------
    ------------- -------- ------ - -------- ----------------- --

    -- ----------
    -------- --------------- -------- ------ -
        -- ----- -- ------- -
            ----- - ------------
        -
        ------ ------
    -

--------
    ---- -----
--

Rule of Five

C++11引入了移动语义,允许资源的所有权从一个对象转移到另一个对象,而不需要进行深拷贝。因此,除了Rule of Three中的三个函数外,还需要考虑移动构造函数和移动赋值运算符。

-- -------------------- ---- -------
----- ------- -
-------
    --------- - -------- ------- --
    ---------- - ------ ----- -  -- -------

    -- ---------
    ------------- -------- ------ - -------- ----------------- --

    -- ----------
    -------- --------------- -------- ------ -
        -- ----- -- ------- -
            ----- - ------------
        -
        ------ ------
    -

    -- ---------
    ----------------- ------ -------- - ---------------- -
        ---------- - --------
    -

    -- ----------
    -------- ------------------- ------ -------- -
        -- ----- -- ------- -
            ------ -----
            ---- - -----------
            ---------- - --------
        -
        ------ ------
    -

--------
    ---- -----
--

Rule of Zero

如果一个类不需要管理任何资源,那么它应该遵循Rule of Zero,即不需要显式定义析构函数、拷贝/移动构造函数或拷贝/移动赋值运算符。编译器会自动生成这些函数的默认版本,通常这些默认版本已经足够。

在这个例子中,MyClass类只包含一个int类型的成员,不需要管理任何动态资源,因此不需要自定义析构函数、拷贝/移动构造函数或拷贝/移动赋值运算符。编译器生成的默认版本已经足够。

纠错
反馈