C++ return Statement: Values, References, RVO, and optional

C++ return Statement: Values, References, RVO, and optional

이 글의 핵심

The return statement finishes execution and passes values back. Learn void returns, reference/pointer pitfalls, RVO, and structured bindings with pair/tuple/optional.

Introduction

The return statement ends a function and passes a value to the caller. In C++, RVO and move semantics often make returning large objects by value efficient—avoid pessimizing with unnecessary std::move on returned locals.


1. return basics

Returning values

#include <iostream>

int add(int a, int b) {
    return a + b;
}

double divide(int a, int b) {
    return static_cast<double>(a) / b;
}

int main() {
    int sum = add(10, 20);
    double result = divide(10, 3);
    
    std::cout << "sum: " << sum << std::endl;
    std::cout << "divide: " << result << std::endl;
    
    return 0;
}

void functions

#include <iostream>

void printMessage(const std::string& msg) {
    std::cout << msg << std::endl;
    return;  // optional at end
}

void processData(int value) {
    if (value < 0) {
        std::cout << "cannot process negative\n";
        return;  // early exit
    }
    std::cout << "processing: " << value << std::endl;
}

2. Return kinds

By value

Returning std::string, std::vector, etc. by value is idiomatic; rely on RVO/move.

Reference returns

Safe patterns: references to members, to static storage, or to parameters passed in—not to locals.

Pointer returns

If you return new, document who deletes. Never return the address of a local automatic variable.


3. RVO / NRVO

Returning a local by name (return s;) enables NRVO in many compilers. Do not write return std::move(s); for a local named return if it blocks elision.


4. Multiple return values

Use std::pair, std::tuple, structs, or C++17 structured bindings. Use std::optional for “maybe a value.”


5. Common problems

Local reference return

const std::string& bad() {
    std::string s = "Hello";
    return s;  // dangling
}

std::string good() {
    std::string s = "Hello";
    return s;  // OK
}

Missing return on some paths

Non-void functions must return on all paths—enable warnings (-Wreturn-type).

Unnecessary std::move on return

Usually harmful for named locals—prefer return local;.


6. Practical file reader example

The Korean article’s FileReader with optional<string> vs throwing readFileOrThrow is a solid pattern for APIs.


Summary

  1. return ends the function and optionally yields a value.
  2. Prefer by value for locals; rely on RVO/move.
  3. References must refer to valid storage.
  4. Pointers imply ownership/lifetime rules—document them.
  5. RVO — avoid std::move on returned named locals unless you know you need it.
  6. optional / tuple / pair for multiple or fallible results.

Next: RVO/NRVO, Copy elision, Move semantics.


  • std::function vs function pointer
  • Default arguments
  • RVO/NRVO errors
  • C++ functions
  • Function overloading