MST

星途 面试题库

面试题:C++ STL容器类型安全与自定义类型

假设有一个自定义类`MyClass`,在使用STL容器(如`list`)存储`MyClass`对象时,如何保证类型安全?特别是在涉及对象拷贝、移动以及异常处理的情况下,如何确保容器中的数据完整性和类型一致性。详细说明你的设计思路,并给出必要的代码片段。
27.8万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试
  1. 设计思路

    • 拷贝构造函数和赋值运算符重载:为MyClass定义拷贝构造函数和赋值运算符重载,确保在拷贝对象时,数据能够正确复制,不会出现浅拷贝等问题,保证数据完整性。
    • 移动构造函数和移动赋值运算符重载:定义移动构造函数和移动赋值运算符重载,提高在移动对象时的效率,同时保证数据的正确转移,避免资源泄漏等问题。
    • 异常安全:在所有可能抛出异常的操作中,确保对象处于一个合理的状态,不会导致数据不一致。比如在构造函数中,如果部分资源分配成功但后续操作抛出异常,要正确释放已分配的资源。
    • 使用std::enable_if和类型 traits:在模板函数或成员函数中,可以使用std::enable_if和类型 traits 来检查类型是否满足特定条件,增强类型安全。例如,确保MyClass满足可拷贝、可移动等条件才能被list存储。
  2. 代码片段

#include <iostream>
#include <list>
#include <type_traits>

class MyClass {
private:
    int data;
public:
    // 构造函数
    MyClass(int value) : data(value) {}

    // 拷贝构造函数
    MyClass(const MyClass& other) : data(other.data) {
        std::cout << "Copy constructor called" << std::endl;
    }

    // 赋值运算符重载
    MyClass& operator=(const MyClass& other) {
        if (this != &other) {
            data = other.data;
            std::cout << "Assignment operator called" << std::endl;
        }
        return *this;
    }

    // 移动构造函数
    MyClass(MyClass&& other) noexcept : data(other.data) {
        other.data = 0;
        std::cout << "Move constructor called" << std::endl;
    }

    // 移动赋值运算符重载
    MyClass& operator=(MyClass&& other) noexcept {
        if (this != &other) {
            data = other.data;
            other.data = 0;
            std::cout << "Move assignment operator called" << std::endl;
        }
        return *this;
    }

    ~MyClass() {
        std::cout << "Destructor called" << std::endl;
    }

    int getData() const {
        return data;
    }
};

template<typename T>
typename std::enable_if<std::is_copy_constructible<T>::value && std::is_move_constructible<T>::value, void>::type
testList() {
    std::list<MyClass> myList;
    MyClass obj1(10);
    myList.push_back(obj1);
    MyClass obj2(20);
    myList.push_back(std::move(obj2));

    for (const auto& obj : myList) {
        std::cout << "Data in list: " << obj.getData() << std::endl;
    }
}

int main() {
    testList<MyClass>();
    return 0;
}

在上述代码中:

  • MyClass类定义了拷贝构造函数、赋值运算符重载、移动构造函数和移动赋值运算符重载,确保在不同操作下数据的完整性和一致性。
  • testList函数使用了std::enable_if和类型 traits 来确保MyClass满足可拷贝和可移动的条件,才进行list的相关操作,增强了类型安全。在main函数中调用testList函数来演示MyClass对象在list中的存储和操作。