面试题答案
一键面试可能遇到的问题
- 数据竞争:多个线程同时访问和修改
std::vector
可能导致数据不一致。例如,一个线程正在删除元素,而另一个线程试图访问或修改相同位置的元素。 - 迭代器失效:在删除
std::vector
中的元素时,迭代器可能会失效。如果在多线程环境下,一个线程删除元素导致迭代器失效,而另一个线程还在使用该失效的迭代器,会引发未定义行为。
利用移动语义和线程同步机制实现
- 移动语义:利用
MyClass
支持的移动语义,可以避免不必要的对象拷贝,提高效率。在将对象从一个std::vector
移动到另一个std::vector
时,使用std::move
。 - 线程同步机制:使用
std::mutex
来保护对std::vector
的访问。在访问或修改std::vector
之前,锁定对应的mutex
,操作完成后解锁。
关键代码示例
#include <iostream>
#include <vector>
#include <mutex>
class MyClass {
public:
MyClass() = default;
MyClass(const MyClass&) = default;
MyClass(MyClass&&) noexcept = default;
MyClass& operator=(const MyClass&) = default;
MyClass& operator=(MyClass&&) noexcept = default;
~MyClass() = default;
};
std::mutex vecMutex;
void removeAndMove(std::vector<MyClass>& source, std::vector<MyClass>& target, const auto& condition) {
std::lock_guard<std::mutex> lock(vecMutex);
auto it = source.begin();
while (it != source.end()) {
if (condition(*it)) {
target.emplace_back(std::move(*it));
it = source.erase(it);
} else {
++it;
}
}
}
你可以这样调用上述函数:
int main() {
std::vector<MyClass> source;
std::vector<MyClass> target;
// 填充source向量
source.emplace_back();
source.emplace_back();
auto condition = [](const MyClass& obj) {
// 这里编写具体的删除条件
return true;
};
removeAndMove(source, target, condition);
return 0;
}
在上述代码中,removeAndMove
函数使用std::lock_guard
来自动管理std::mutex
的锁定和解锁。在锁定mutex
后,遍历source
向量,满足条件的MyClass
对象通过std::move
移动到target
向量中,并从source
向量中删除。这样既保证了线程安全,又利用了移动语义提高效率。