| 特性 | void | 值返回 | 常量值返回 | 返回指针 | 返回引用 | 返回 const 引用 |
|---|---|---|---|---|---|---|
| 语法 | void f() | T f() | const T f() | T* f() | T& f() | const T& f() |
| 返回值 | 无 | 对象的副本 | const 副本 | 对象指针 | 对象引用 | const 对象引用 |
| 能否修改返回值 | ❌ 不适用 | ✅ 是 | ❌ 否 | ✅ 是(通过指针) | ✅ 是 | ❌ 否 |
| 是否拷贝 | — | ✅ 是(有 RVO 优化) | ✅ 是 | ❌ 否 | ❌ 否 | ❌ 否 |
| 返回局部变量 | ✅ 可以 | ✅ 可以(RVO) | ✅ 可以 | ❌ 危险 | ❌ 危险 | ❌ 危险 |
| 典型用途 | 执行操作无结果 | 安全返回小型对象 | 防止误用返回值 | 动态内存、C 风格 API | 链式调用、避免拷贝 | 只读大型对象 |
选择建议:
- 小型对象/只读:使用 值返回 + RVO(最安全)
- 大型对象:使用 返回 const 引用(避免拷贝)
- 需要修改:使用 返回引用
- 动态分配/兼容 C:使用 返回指针
- 无返回值:使用 void
返回 void
void 表示函数不返回任何值。
cpp
void printHello() {
std::cout << "Hello!" << std::endl;
// 无需 return 语句
}
int main() {
printHello(); // 调用后继续执行
}- 可使用
return;提前退出 - 不能在
void函数中返回任何值 - 常用于执行操作而非计算结果的函数
返回值
值返回
返回对象的副本(拷贝或移动):
cpp
int getNumber() {
int n = 42;
return n; // 将 n 的值拷贝一份传出去
}
int main() {
int val = getNumber(); // val 得到了 42 的副本
val = 100; // 修改 val 完全不会影响函数内部曾经的 n
return 0;
}特点:调用方拥有独立的数据副本,安全且互不干扰。
现代优化:虽然逻辑上是“拷贝”,但对于大型对象,编译器通常会使用 RVO (返回值优化) 直接在接收方内存中构造对象,性能非常高。
常量值返回
返回 const 副本,调用者不能修改返回值:
cpp
const int getConstant() {
return 10;
}
int main() {
// 情况 A:赋值给非 const 变量(合法)
int a = getConstant();
a = 20; // 合法,因为 a 本身不是 const,它只是拷贝了那个 10
// 情况 B:直接对返回值进行操作(报错)
// getConstant() = 20; // 错误!返回值是 const
}- 对于内置类型返回
const无意义
返回值优化
返回值优化(RVO)是一种编译器优化技术,避免在返回局部对象时进行不必要的拷贝或移动。
函数在返回局部对象时,传统方式需要:
- 在函数内构造对象
- 拷贝/移动到返回值
- 销毁局部对象
优化后:直接在调用者位置构造对象,零拷贝。
cpp
std::string getName() {
std::string name = "Alice"; // 局部变量
return name; // 不拷贝!
}
int main() {
std::string s = getName(); // 直接构造,无拷贝
}- 在现代 C++ 中,返回值,通常是最安全、最清晰、也是最容易优化的选择。
必须满足的条件:
- 返回局部对象:不能说静态变量或全局变量
- 返回类型一致:返回的对象类型和函数返回类型相同
- 无分支返回不同对象:避免混淆优化
⚠️注意事项:
cpp
// 不要手动返回 std::move
std::string getName() {
std::string name = "Alice";
return std::move(name); // ❌ 不推荐!可能阻碍 RVO
}- 主动
std::move(),编译器反而不能做 RVO。 - 返回局部变量时,不要写
std::move(),让编译器发挥
返回指针
返回 void*
cpp
void* allocate(size_t size) {
return malloc(size);
}
int main() {
void *ptr = allocate(1024);
int *intPtr = static_cast<int*>(ptr);
free(ptr);
}返回引用
返回引用允许函数直接返回对象的引用,而非副本。
cpp
int& func(int &x) {
return x; // 返回参数的引用
}- 避免拷贝:返回大型对象时高效
- 允许修改:可以用于赋值操作
- 支持链式调用
返回 const 引用
cpp