void函数不能带返回值表达式,仅允许return;;main函数必须返回int而非void;返回类型决定临时对象构造与生命周期,影响移动/拷贝及内存安全。

void 函数不能带返回值表达式
当你写 void func(),函数体内出现 return 5; 或 return someString; 就会直接编译失败。编译器明确拒绝这种写法,因为 void 表示“不产出任何值”,而带表达式的 return 暗示要交出一个东西。
但你可以写 return;(无表达式),它只是提前退出函数,等价于走到函数末尾自动返回。常见用法包括:条件提前终止、避免嵌套过深、或在异常路径上快速退出。
- 错误示范:
void log_error() { return "failed"; }→ 编译报错:error: cannot convert 'const char*' to 'void' in return - 正确写法:
void log_error() { std::cerr (<code>return;可省略) - 注意:即使调用另一个
void函数,也不能把它当值用,比如return other_void_func();是合法的(因为other_void_func()返回void),但毫无意义,且多数编译器会警告
有返回值函数必须每条 return 都带匹配类型的值
只要函数声明了非 void 返回类型(如 int、std::string、const char*),那么所有可能执行到的 return 语句都必须提供一个值,且该值能隐式转换为目标类型。
漏写、写错类型、或控制流存在无 return 的分支,都会触发编译错误或未定义行为(尤其后者:某些路径没 return,但编译器没报错,运行时可能返回垃圾值)。
立即学习“C++免费学习笔记(深入)”;
- 危险写法:
int find_first_positive(const std::vector<int>& v) { for (int x : v) if (x > 0) return x; }</int>→ 如果v全为负数,函数无return,行为未定义 - 安全写法:补上兜底
return,例如return -1;或抛异常,或用[[noreturn]]明确标注不会返回 - 类型要对得上:声明为
double calc(),就不能return "3.14";;但return 3;可以,因为int→double是标准隐式转换
返回值类型决定了临时对象的构造方式
C++ 在 return 时不是“把局部变量搬出去”,而是用返回值类型去**初始化一个临时对象**——这个临时对象再用于初始化调用点的接收变量(如 auto x = func();)。所以返回类型不是装饰,它真实参与对象生命周期和拷贝/移动决策。
比如返回 std::string 和返回 const std::string& 看似只差个引用符号,但语义天差地别:前者可能触发移动构造(如果返回的是局部对象),后者若引用局部变量就是悬垂引用(UB)。
- 安全返回值:
std::string get_name() { return "Alice"; }→ 字符串字面量构造临时std::string,再移入接收变量 - 危险返回引用:
const std::string& bad_ref() { std::string s = "Bob"; return s; }→s出作用域即销毁,返回引用指向已释放内存 - void 函数没这层机制:它不构造任何返回临时量,也就不存在“返回什么”的生命周期问题
main 函数必须是 int,不是 void
哪怕你只写 void main() 并且代码能编译通过(某些旧编译器或嵌入式环境允许),它也违反 C++ 标准。标准规定 main 必须返回 int,操作系统靠这个整数判断程序是否成功结束。
省略 return 语句在 int main() 中是特例:编译器自动补 return 0;;但在 void main() 中,连这个保障都没有,且移植到其他平台大概率失败。
- 正确写法:
int main() { /* ... */ return 0; }或干脆不写return,靠隐式return 0; - 错误写法:
void main() { }→ 不符合 ISO C++,Clang/GCC 在严格模式下直接拒绝 - 注意:有些教程或老书用
void main(),那是过时或非标准实践,不要模仿
真正容易被忽略的是:返回类型不仅约束语法,还绑定对象构造时机、内存生命周期和 ABI 兼容性。写 void 不是为了“省事”,而是明确放弃值传递契约;而一旦承诺返回某个类型,就要对它的构造、移动、甚至是否可拷贝,负全责。


















