面试题答案
一键面试1. 使用移动语义
移动语义允许我们在对象所有权转移时避免不必要的复制,而是将资源从一个对象“移动”到另一个对象。在C++ 11及之后,通过定义移动构造函数和移动赋值运算符来实现。
#include <iostream>
#include <vector>
class BigObject {
public:
std::vector<int> data;
// 构造函数
BigObject(int size) : data(size) {
std::cout << "Constructor: Allocating data of size " << size << std::endl;
}
// 移动构造函数
BigObject(BigObject&& other) noexcept : data(std::move(other.data)) {
std::cout << "Move Constructor: Moving data" << std::endl;
}
// 移动赋值运算符
BigObject& operator=(BigObject&& other) noexcept {
if (this != &other) {
data = std::move(other.data);
std::cout << "Move Assignment: Moving data" << std::endl;
}
return *this;
}
// 析构函数
~BigObject() {
std::cout << "Destructor: Deallocating data" << std::endl;
}
};
void processObject(BigObject obj) {
std::cout << "Processing object with data size: " << obj.data.size() << std::endl;
}
int main() {
BigObject bigObj(1000000);
processObject(std::move(bigObj));
return 0;
}
在上述代码中,BigObject
类有一个大的std::vector<int>
成员。移动构造函数和移动赋值运算符将other
对象的data
资源移动到当前对象,避免了复制。在main
函数中,通过std::move
将bigObj
移动到processObject
函数,触发移动语义。
2. 返回值优化(RVO)
返回值优化(RVO)是一种编译器优化技术,当函数返回一个对象时,编译器可以直接在调用者的栈空间构造该对象,避免了额外的复制或移动操作。
#include <iostream>
#include <vector>
class BigObject {
public:
std::vector<int> data;
// 构造函数
BigObject(int size) : data(size) {
std::cout << "Constructor: Allocating data of size " << size << std::endl;
}
// 析构函数
~BigObject() {
std::cout << "Destructor: Deallocating data" << std::endl;
}
};
BigObject createBigObject() {
return BigObject(1000000);
}
int main() {
BigObject obj = createBigObject();
return 0;
}
在这个例子中,createBigObject
函数返回一个BigObject
对象。编译器通常会应用RVO,直接在main
函数的obj
对象位置构造BigObject
,而不是先构造一个临时对象再复制或移动到obj
。
3. 使用引用传递
使用常量引用传递大对象可以避免复制,适用于函数内部不需要修改对象的场景。
#include <iostream>
#include <vector>
class BigObject {
public:
std::vector<int> data;
// 构造函数
BigObject(int size) : data(size) {
std::cout << "Constructor: Allocating data of size " << size << std::endl;
}
// 析构函数
~BigObject() {
std::cout << "Destructor: Deallocating data" << std::endl;
}
};
void processObject(const BigObject& obj) {
std::cout << "Processing object with data size: " << obj.data.size() << std::endl;
}
int main() {
BigObject bigObj(1000000);
processObject(bigObj);
return 0;
}
在这个代码中,processObject
函数接受一个const BigObject&
参数,避免了对象的复制。由于参数是const
,函数内部不能修改对象。