返回值返回引用返回指针之间的区别

一、返回值

当函数返回一个值时,实际返回的是一个变量的拷贝。

优点:

  • 简单易用;
  • 安全,不会导致悬挂指针或悬挂引用;

缺点:

  • 当返回值是一个较大的对象时会产生拷贝开销,影响程序性能;
二、返回引用

当函数返回一个引用时,实际返回的是变量的别名。

优点:

  • 没有拷贝开销,不影响程序性能;
  • 可以用于返回对象本身,实现链式调用;

缺点:

  • 如果是局部变量的引用,会导致未定义行为(悬挂引用);
三、返回指针

当函数返回一个指针时,实际返回的是一个变量的地址。

优点:

  • 灵活性高
  • 可用于动态分配内存的返回;

缺点:

  • 不安全,可能产生内存泄漏;
  • 可能导致悬挂指针(返回了一个已经释放的内存);
四、总结

(1)适用场景

  • 返回值:适用于基本数据类型或小对象 ,不需要考虑性能问题。或需要使用临时对象的场景。
  • 返回引用:适用于较大的对象 ,需要考虑性能问题的场景。
  • 返回指针:适用于动态分配内存或指针灵活指向的场景。

(2)注意事项

  • 返回局部对象或局部变量时:局部变量和局部对象在使用后会被销毁 ,返回它们的引用会产生悬挂引用或悬挂指针。使用这些引用会产生未定义行为。
  • 内存管理: 对于函数内部手动分配的内存 ,在适当的时候需要进行销毁 ,以避免内存泄漏。不能返回指向已经被销毁的内存空间的指针。 如果函数返回一个指向动态分配内存的指针,在使用结束后必须手动销毁这段内存,以避免内存泄漏。
五、代码实例
#include <iostream>
#include <stdexcept>
#include <string>

using namespace std;

class Person
{
public:
    Person() {} // 默认构造
    Person(std::string name, int age, std::string sex) :name(name), age(age), sex(sex) {}   // 带参构造
    Person(const Person& p)
    {
        this->name = p.name;
        this->age = p.age;
        this->sex = p.sex;
        std::cout << std::endl << "对象拷贝" << std::endl;
    }
    friend std::ostream& operator<<(std::ostream& os, const Person& p);

private:
    std::string name;
    int age;
    std::string sex;
};

std::ostream& operator<<(std::ostream& os,const Person& p)
{
    os << "姓名: " << p.name << std::endl << "年龄: " << p.age << std::endl << "性别: " << p.sex << std::endl;
    return os;
}

// 返回值
int getInt()    
{
    int x = 10;
    return x;
}

// 返回引用
int& getIntReference(int &x)  
{
    return x;   // 返回 x 的引用
}

// 返回指针
int* getIntPointer(int* x)  
{
    if (x == nullptr) {
        throw std::invalid_argument("不能返回一个空指针");
    }
    return x;   // 返回 x 的地址
}

/* 
* 返回局部对象的引用
*/
Person& getLocalIntReference()
{
    // 不允许返回局部对象的引用,抛出异常
    throw std::runtime_error("不允许返回局部对象的引用");
}

/*
* 返回局部指针
*/
int* getLocalIntPointer()
{
    int arr[4] = { 1,2,3,4 };
    // 不允许返回局部指针,抛出异常
    throw std::runtime_error("不允许返回局部指针");
}

/*
* 返回动态分配的内存
*/
int* getMotionIntPointer()
{
    int* x = new int(10);
    if (x == nullptr) {
        throw std::runtime_error("不能返回一个空指针");
    }
    return x;
}

int main()
{
    try {
        std::cout << "返回值: " << getInt() << std::endl;
        
        int temp = getInt();
        std::cout << "返回引用: " << getIntReference(temp) << std::endl;
        
        int temp2 = getInt();
        std::cout << "返回指针: " << getIntPointer(&temp2) << std::endl;
        
        std::cout << "返回局部引用: " << getLocalIntReference() << std::endl;  // 会抛出异常
    } catch (const std::exception& e) {
        std::cerr << "捕获的异常: " << e.what() << std::endl;
    }

    try {
        std::cout << "返回局部指针: " << getLocalIntPointer() << std::endl;  // 会抛出异常
    } catch (const std::exception& e) {
        std::cerr << "捕获的异常: " << e.what() << std::endl;
    }

    try {
        int* ptr = getMotionIntPointer();
        std::cout << "返回动态内存: " << *ptr << std::endl;
        delete ptr;  // 确保释放动态分配的内存
    } catch (const std::exception& e) {
        std::cerr << "捕获的异常: " << e.what() << std::endl;
    }

    return 0;
}

六、运行结果

在这里插入图片描述

文章部分内容使用了ChatGPT,如有谬误,请各位大佬留言指正!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值