返回常量引用
- 适用场景:当函数返回的对象是一个已经存在的、不会被函数修改的临时对象,并且该对象的生命周期在函数结束后依然有效时,适合返回常量引用。例如,函数返回类内部的成员变量(前提是该成员变量不会在函数结束后被销毁)。
- 优点:
- 性能高:避免了对象的拷贝构造,直接返回对象的引用,对于大型对象或拷贝构造开销大的对象,性能提升明显。
- 避免临时对象创建:不会创建额外的临时对象用于返回值传递。
- 缺点:
- 生命周期限制:返回的对象必须在函数结束后依然存在。如果返回局部对象的引用,会导致悬空引用,程序运行时会出现未定义行为。
- 不能修改返回值:由于是常量引用,调用者不能修改返回的对象。
- 代码示例:
class MyClass {
public:
MyClass() = default;
MyClass(const MyClass&) { std::cout << "Copy constructor called" << std::endl; }
~MyClass() = default;
private:
int data = 0;
friend const MyClass& getInstance();
};
const MyClass& getInstance() {
static MyClass instance;
return instance;
}
返回值传递
- 适用场景:当函数返回的对象是一个全新创建的对象,且函数结束后该对象不再需要保留其在函数内的状态,调用者需要拥有该对象的独立副本时,适合返回值传递。例如,函数内部创建了一个局部对象并返回。
- 优点:
- 灵活性高:调用者得到的是一个独立的对象副本,可以自由修改。
- 不存在生命周期问题:不用担心返回的对象在函数结束后被销毁,因为调用者得到的是新创建的副本。
- 缺点:
- 性能开销:会调用拷贝构造函数(C++11 引入了移动语义后,在某些情况下可以优化为移动构造),对于大型对象或拷贝构造开销大的对象,性能会受到影响。
- 创建临时对象:需要创建临时对象用于返回值传递。
- 代码示例:
class MyClass {
public:
MyClass() = default;
MyClass(const MyClass&) { std::cout << "Copy constructor called" << std::endl; }
~MyClass() = default;
private:
int data = 0;
};
MyClass createObject() {
MyClass obj;
return obj;
}