
🔥个人主页:艾莉丝努力练剑 ❄专栏传送门:《C语言》、《数据结构与算法》、C语言刷题12天IO强训、LeetCode代码强化刷题、C/C++干货分享&学习过程记录 🍉学习方向:C/C++方向 ⭐️人生格言:为天地立心,为生民立命,为往圣继绝学,为万世开太平
前言:本专栏记录了博主C++从初阶到高阶完整的学习历程,会发布一些博主学习的感悟、碰到的问题、重要的知识点,和大家一起探索C++这门程序语言的奥秘。这个专栏将记录博主C++语法、高阶数据结构、STL的学习过程,正所谓“万丈高楼平地起”嘛,我们话不多说,继续进行C++阶段的学习。本文我们不讲C++主线的内容,我们来拓展一下或者说整理一下我们学习时C/C++时经常会提到的一些专有名词,例如形参、实参,显式类型转换和隐式类型转换类型转换,内置类型、引用、传值返回和传引用返回等等。
C++的两个参考文档:
老朋友(非官方文档):cplusplus 官方文档(同步更新):cppreference
博主之前写了传值返回和传引用返回相关的内容,只不过那是在C++初识部分介绍的,比较简略:
【C/C++】初识C++(二):深入详解缺省参数(默认参数)函数重载、引用(重头戏)
【C/C++】初识C++(三):C++入门内容收尾——const引用,指针和引用关系梳理,inline(内联函数),nullptr替代NULL
传值返回是指函数返回对象的一个副本,调用方获得的是与原对象完全独立的新对象。
// 基本类型传值返回
int add(int a, int b)
{
return a + b; // 返回int类型的值
}
// 对象传值返回
std::string createGreeting(const std::string& name)
{
return "Hello, " + name + "!"; // 返回新构造的string对象
}
// 返回局部对象(安全)
std::vector<int> generateNumbers()
{
std::vector<int> nums {1, 2, 3, 4, 5};
return nums; // 返回拷贝(可能被RVO优化)
}std::string func()
{
return std::string("hello"); // 可能直接在调用方内存构造
}std::string func()
{
std::string s = "hello";
return s; // 可能直接在调用方内存构造
}传引用返回是指函数返回对象的引用(别名),调用方获得的是对原对象的直接引用。
// 返回静态变量的引用(安全)
const std::string& getVersion() {
static const std::string ver = "1.0.0";
return ver;
}
// 返回成员变量的引用
class Container {
std::vector<int> data;
public:
// const引用返回
const std::vector<int>& getData() const { return data; }
// 非const引用返回(允许修改)
std::vector<int>& getMutableData() { return data; }
};
// 返回参数引用(需确保参数生命周期)
const std::string& longerString(
const std::string& a,
const std::string& b) {
return a.length() > b.length() ? a : b;
}// 危险示例1:返回局部变量引用
const int& dangerous1() {
int x = 42;
return x; // x将被销毁!
}
// 危险示例2:返回临时对象引用
const std::string& dangerous2() {
return "temporary"; // 临时对象将销毁!
}
// 危险示例3:返回悬空指针的引用
const std::string& dangerous3() {
std::string* s = new std::string("hello");
return *s; // 内存泄漏风险
}比较维度 | 传值返回 | 传引用返回 |
|---|---|---|
返回内容 | 对象副本 | 对象别名 |
拷贝开销 | 可能有(但常被优化) | 无 |
修改原对象 | 不能 | 可以(非const引用) |
安全性 | 高 | 需注意生命周期 |
适用对象大小 | 小型对象 | 中大型对象 |
典型用例 | 工厂函数、计算函数 | 访问器、链式调用 |
RVO优化 | 支持 | 不适用 |
C++11移动语义 | 可结合使用 | 不适用 |
// 现代C++编译器能很好优化
std::vector<int> getData()
{
return {1, 2, 3}; // 依赖RVO/NRVO
}// 场景1:返回类成员
class Config
{
std::string path;
public:
const std::string& getPath() const
{
return path;
}
};
// 场景2:链式调用
class Builder
{
std::string data;
public:
Builder& append(const std::string& s)
{
data += s;
return *this;
}
};// 只读访问用const引用
const std::string& getName() const;
// 需要修改用非const引用
std::string& getMutableName();// 移动语义支持
std::unique_ptr<Resource> createResource()
{
auto res = std::make_unique<Resource>();
res->initialize();
return res; // 移动而非拷贝
}
// 返回右值引用
std::vector<int>&& extractData()
{
std::vector<int> temp;
// ...填充数据
return std::move(temp); // 明确所有权转移
}// 参数+返回优化
void computeResult(Input in, Result& out)
{
// 直接填充out避免拷贝
}
// 或者返回智能指针
std::shared_ptr<BigData> createBigData()
{
return std::make_shared<BigData>();
}我们在选择具体的返回方式需要综合考虑对象生命周期、性能需求、接口设计等多个因素。
往期回顾:
【日常问题解决方案】VS2022不小心解决方案资源管理器把关掉了怎么办
结语:本文内容到这里就全部结束了。本文我们重新整理了C++传值返回和传引用返回相关的内容,希望对大家有所帮助。