C 函数的返回值

在C 中,函数的返回值是函数执行完毕后传递给调用方的数据。以下是关键概念和注意事项:

1. 基本语法

cpp

返回类型 函数名(参数列表) {

// 函数体

return 表达式; // 返回值的核心语句

}

- 返回类型:定义返回值的数据类型(如 `int`, `double`, `string` 等)

- `return` 语句:终止函数执行并将表达式结果传递给调用方

2. 返回值类型

- 基本类型:直接返回数据副本

cpp

int add(int a, int b) {

return a b; // 返回int类型副本

}

- 引用类型:返回变量的引用(避免拷贝开销)

cpp

int& getMax(int& x, int& y) {

return (x > y) ? x : y; // 返回引用

}

- 指针类型:返回内存地址

cpp

int* createArray(int size) {

return new int[size]; // 返回动态数组指针

}

- `void` 类型:无返回值

cpp

void printLog() {

cout << Executed 无需return

}

3. 核心规则

- 类型匹配:返回值必须与声明类型严格匹配

- 单次返回:函数每次调用最多执行一次 `return`(允许多个条件分支)

- 生命周期:禁止返回局部变量的引用或指针(函数结束即销毁)

cpp

int* invalidReturn() {

int local = 10;

return &local; // 错误!局部变量地址失效

}

4. 返回值优化(RVO)

编译器自动优化减少拷贝开销:

cpp

std::string buildName() {

return Alice 直接构造返回值,避免临时对象拷贝

}

5. 结构化绑定(C 17)

返回元组或多值:

cpp

auto getUser() -> std::tuple {

return {101, 返回多值

}

// 调用示例

auto [id, name] = getUser(); // 解包返回值

6. 特殊返回类型

- `auto` 推导(C 14 ):

cpp

auto multiply(double a, double b) {

return a * b; // 编译器推导返回类型为double

}

- `decltype(auto)`(C 14 ):

cpp

decltype(auto) getRef(int& x) {

return x; // 精确保持引用类型

}

7. 错误处理

- 异常机制:通过 `throw` 返回错误(非返回值路径)

cpp

int safeDivide(int a, int b) {

if (b == 0) throw std::runtime_error( by zeron return a / b;

}

- `std::optional`(C 17):

cpp

std::optional tryParse(std::string s) {

try { return std::stoi(s); }

catch (...) { return std::nullopt; } // 表示无值

}

最佳实践

1. 优先返回值而非输出参数

2. 返回引用时确保对象生命周期长于函数调用

3. 对大型对象使用 RVO 或移动语义(`std::move`)

4. 用 `const` 修饰不可修改的返回值

cpp

const std::string& getConstantName();

> 示例:计算二次方程 $ax^2 bx c = 0$ 的实根

> cpp

> #include

> #include

> #include

>

> std::optional> solveQuadratic(double a, double b, double c) {

> double discriminant = b*b4*a*c;

> if (discriminant < 0) return std::nullopt; // 无实根

>

> double root1 = (-b std::sqrt(discriminant)) / (2*a);

> double root2 = (-bstd::sqrt(discriminant)) / (2*a);

> return std::make_tuple(root1, root2);

> }

>

C 函数的返回值

在C 中,函数返回值是函数执行后传递给调用者的数据。以下是关键概念和注意事项:

1. 基本返回类型

- 值返回:直接返回数据副本(适用于小型数据)

cpp

int add(int a, int b) {

return a b; // 返回int值

}

- 引用返回:避免拷贝,返回已有对象的引用(需确保对象生命周期)

cpp

int& getMax(int& a, int& b) {

return (a > b) ? a : b; // 返回引用

}

- 指针返回:返回内存地址(需注意内存管理)

cpp

int* createArray(int size) {

return new int[size]; // 返回动态数组指针

}

- `void`类型:无返回值

cpp

void printHello() {

std::cout <<

2. 返回优化机制

- RVO (Return Value Optimization)

编译器优化,避免临时对象拷贝:

cpp

std::vector makeVector() {

return std::vector{1, 2, 3}; // 可能直接构造在调用处

}

- NRVO (Named RVO)

对命名变量的优化:

cpp

std::string getName() {

std::string name = Alicen return name; // 编译器可能避免拷贝

}

3. 现代C 特性

- 返回自动推导 (`auto`)

C 14 支持自动推导返回类型:

cpp

auto multiply(double x, double y) {

return x * y; // 推导为double

}

- 结构化绑定 (C 17)

返回元组/结构体并解包:

cpp

std::tuple getData() {

return {42, 3.14};

}

// 调用处

auto [num, val] = getData();

4. 重要注意事项

- 悬空引用/指针

禁止返回局部变量的引用或指针:

cpp

int& dangerousFunc() {

int x = 10;

return x; // 错误!x将销毁

}

- 返回值生命周期

返回临时对象时需注意移动语义:

cpp

std::unique_ptr createInt() {

return std::make_unique(100); // 安全移动

}

- 返回类型一致性

所有分支必须返回相同类型:

cpp

int check(int a) {

if (a > 0) return 1;

else return -1; // 所有路径返回int

}

示例:返回不同类型

cpp

#include

#include

// 返回值

int square(int x) { return x * x; }

// 返回引用

std::string& getStaticString() {

static std::string s =

return s;

}

// 返回元组 (C 17)

auto getCoordinates() {

return std::make_tuple(10.5, 20.3);

}

int main() {

std::cout << square(5) <<

// 25

getStaticString() = Modifiedn std::cout << getStaticString() <<

// Modified

auto [x, y] = getCoordinates();

std::cout << : < x << Y: << y;

}

输出:

25

Modified

X: 10.5, Y: 20.3

最佳实践

1. 小型数据:直接返回值

2. 大型对象:使用移动语义或返回智能指针

3. 需修改外部状态:返回引用(确保对象有效)

4. 多返回值:使用`std::tuple`或结构体

5. 避免返回原始指针(优先使用智能指针)

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐