值传递(Pass by Value)

基本概念

值传递是将实参的值复制给形参,函数内部操作的是副本,不会影响原始变量。

void modifyValue(int x) {
    x = 100;  // 只修改局部副本
    std::cout << "Inside function: " << x << std::endl;  // 100
}
 
int main() {
    int a = 10;
    modifyValue(a);
    std::cout << "After function: " << a << std::endl;  // 10,未改变
    return 0;
}

对象的值传递

class Person {
public:
    std::string name;
    int age;
    
    Person(const std::string& n, int a) : name(n), age(a) {
        std::cout << "Constructor called for " << name << std::endl;
    }
    
    Person(const Person& other) : name(other.name), age(other.age) {
        std::cout << "Copy constructor called for " << name << std::endl;
    }
    
    ~Person() {
        std::cout << "Destructor called for " << name << std::endl;
    }
};
 
void processPerson(Person p) {  // 值传递,会调用拷贝构造函数
    p.age = 100;  // 只修改副本
    std::cout << "Inside function: " << p.name << " is " << p.age << std::endl;
}
 
int main() {
    Person alice("Alice", 25);
    processPerson(alice);  // 触发拷贝构造函数
    std::cout << "After function: " << alice.name << " is " << alice.age << std::endl;
    return 0;
}
// 输出:
// Constructor called for Alice
// Copy constructor called for Alice
// Inside function: Alice is 100
// Destructor called for Alice  (副本析构)
// After function: Alice is 25
// Destructor called for Alice  (原对象析构)

值传递的优缺点

// 优点:安全,不会意外修改原始数据
int safeCalculation(int value) {
    value *= 2;  // 不影响原始值
    return value;
}
 
// 缺点:性能开销,特别是大对象
void inefficientFunction(std::vector<int> vec) {  // 拷贝整个 vector
    // 处理 vec
}
 
// 改进:使用 const 引用
void efficientFunction(const std::vector<int>& vec) {  // 不拷贝
    // 处理 vec,但不能修改
}

引用传递(Pass by Reference)

基本引用传递

void modifyReference(int& x) {
    x = 100;  // 直接修改原始变量
}
 
void swap(int& a, int& b) {
    int temp = a;
    a = b;
    b = temp;
}
 
int main() {
    int x = 10, y = 20;
    modifyReference(x);
    std::cout << "x = " << x << std::endl;  // 100
    
    swap(x, y);
    std::cout << "x = " << x << ", y = " << y << std::endl;  // x = 20, y = 100
    return 0;
}

常量引用传递

// 避免拷贝,同时防止修改
void printPerson(const Person& p) {
    std::cout << p.name << " is " << p.age << " years old" << std::endl;
    // p.age = 30;  // 编译错误!不能修改 const 引用
}
 
// 返回引用以支持链式调用
class Counter {
    int count = 0;
public:
    Counter& increment() {
        ++count;
        return *this;  // 返回自身引用
    }
    
    Counter& add(int value) {
        count += value;
        return *this;
    }
    
    int getValue() const { return count; }
};
 
int main() {
    Counter c;
    c.increment().add(5).increment();  // 链式调用
    std::cout << c.getValue() << std::endl;  // 7
}

引用的限制和注意事项

// 引用必须初始化
void function() {
    int& ref;  // 编译错误!引用必须初始化
}
 
// 引用不能重新绑定
void rebindReference() {
    int a = 10, b = 20;
    int& ref = a;
    ref = b;  // 这是赋值,不是重新绑定!ref 仍然引用 a
    std::cout << a << std::endl;  // 20,a 的值被改变了
}
 
// 不能创建引用的数组
void arrayOfReferences() {
    int a = 1, b = 2;
    // int& refs[] = {a, b};  // 编译错误!
}
 
// 返回局部变量的引用是危险的
int& dangerousFunction() {
    int local = 42;
    return local;  // 危险!返回局部变量的引用
}  // local 在这里被销毁
 
// 安全的引用返回
class SafeContainer {
    std::vector<int> data;
public:
    int& at(size_t index) {
        return data.at(index);  // 返回容器元素的引用
    }
    
    const int& at(size_t index) const {
        return data.at(index);  // const 版本
    }
};

指针传递(Pass by Pointer)

基本指针传递

void modifyPointer(int* x) {
    if (x != nullptr) {
        *x = 100;  // 修改指针指向的值
    }
}
 
void allocateMemory(int** ptr) {
    *ptr = new int(42);  // 修改指针本身
}
 
int main() {
    int a = 10;
    modifyPointer(&a);
    std::cout << "a = " << a << std::endl;  // 100
    
    int* p = nullptr;
    allocateMemory(&p);
    std::cout << "*p = " << *p << std::endl;  // 42
    delete p;  // 记得释放内存
    
    return 0;
}

指针与数组

// 数组作为参数实际上是指针
void printArray(int arr[], int size) {  // 等价于 int* arr
    for (int i = 0; i < size; i++) {
        std::cout << arr[i] << " ";
    }
    std::cout << std::endl;
}
 
// 多维数组
void print2DArray(int arr[][3], int rows) {  // 第一维可以省略,其他维不能
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < 3; j++) {
            std::cout << arr[i][j] << " ";
        }
        std::cout << std::endl;
    }
}
 
// 使用指针的指针
void print2DArrayPtr(int** arr, int rows, int cols) {
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            std::cout << arr[i][j] << " ";
        }
        std::cout << std::endl;
    }
}

智能指针传递

#include <memory>
 
// 传递 unique_ptr
void processUniquePtr(std::unique_ptr<int> ptr) {  // 转移所有权
    std::cout << "Value: " << *ptr << std::endl;
    // ptr 在函数结束时自动释放
}
 
void processUniquePtrRef(const std::unique_ptr<int>& ptr) {  // 不转移所有权
    if (ptr) {
        std::cout << "Value: " << *ptr << std::endl;
    }
}
 
// 传递 shared_ptr
void processSharedPtr(std::shared_ptr<int> ptr) {  // 增加引用计数
    std::cout << "Value: " << *ptr << std::endl;
    std::cout << "Reference count: " << ptr.use_count() << std::endl;
}
 
int main() {
    auto unique_ptr = std::make_unique<int>(42);
    processUniquePtrRef(unique_ptr);  // 不转移所有权
    // processUniquePtr(std::move(unique_ptr));  // 转移所有权
    
    auto shared_ptr = std::make_shared<int>(100);
    std::cout << "Before: " << shared_ptr.use_count() << std::endl;  // 1
    processSharedPtr(shared_ptr);  // 临时增加引用计数
    std::cout << "After: " << shared_ptr.use_count() << std::endl;   // 1
    
    return 0;
}

右值引用和移动语义(C++11)

右值引用基础

// 左值引用 vs 右值引用
void processLValue(int& x) {
    std::cout << "LValue: " << x << std::endl;
}
 
void processRValue(int&& x) {
    std::cout << "RValue: " << x << std::endl;
}
 
// 重载解析
void process(const std::string& s) {
    std::cout << "LValue/const: " << s << std::endl;
}
 
void process(std::string&& s) {
    std::cout << "RValue: " << s << std::endl;
}
 
int main() {
    int a = 10;
    processLValue(a);      // OK,a 是左值
    // processLValue(20);  // 错误!20 是右值
    
    processRValue(20);     // OK,20 是右值
    // processRValue(a);   // 错误!a 是左值
    
    std::string str = "hello";
    process(str);                    // 调用左值版本
    process("world");                // 调用右值版本
    process(std::move(str));         // 强制调用右值版本
    
    return 0;
}

移动构造和移动赋值

class MoveableClass {
    std::vector<int> data;
    std::string name;
    
public:
    // 构造函数
    MoveableClass(const std::string& n) : name(n) {
        data.resize(1000000);  // 大量数据
        std::cout << "Constructor: " << name << std::endl;
    }
    
    // 拷贝构造函数
    MoveableClass(const MoveableClass& other) 
        : data(other.data), name(other.name) {
        std::cout << "Copy constructor: " << name << std::endl;
    }
    
    // 移动构造函数
    MoveableClass(MoveableClass&& other) noexcept
        : data(std::move(other.data)), name(std::move(other.name)) {
        std::cout << "Move constructor: " << name << std::endl;
    }
    
    // 拷贝赋值运算符
    MoveableClass& operator=(const MoveableClass& other) {
        if (this != &other) {
            data = other.data;
            name = other.name;
            std::cout << "Copy assignment: " << name << std::endl;
        }
        return *this;
    }
    
    // 移动赋值运算符
    MoveableClass& operator=(MoveableClass&& other) noexcept {
        if (this != &other) {
            data = std::move(other.data);
            name = std::move(other.name);
            std::cout << "Move assignment: " << name << std::endl;
        }
        return *this;
    }
};
 
// 函数参数中的移动语义
void processByValue(MoveableClass obj) {  // 可能触发移动
    // 使用 obj
}
 
void processByRValueRef(MoveableClass&& obj) {  // 接受右值
    // 可以移动 obj 的内容
    MoveableClass local = std::move(obj);
}
 
int main() {
    MoveableClass obj1("Object1");
    
    // 拷贝
    MoveableClass obj2 = obj1;  // 拷贝构造
    
    // 移动
    MoveableClass obj3 = std::move(obj1);  // 移动构造
    
    // 函数调用
    processByValue(MoveableClass("Temp"));  // 移动构造(临时对象)
    processByRValueRef(MoveableClass("Temp2"));  // 直接构造
    
    return 0;
}

完美转发(Perfect Forwarding)

#include <utility>
 
// 转发函数,保持参数的值类别
template<typename T>
void wrapper(T&& arg) {
    // std::forward 保持 arg 的值类别
    actualFunction(std::forward<T>(arg));
}
 
// 实际处理函数
void actualFunction(const std::string& s) {
    std::cout << "LValue: " << s << std::endl;
}
 
void actualFunction(std::string&& s) {
    std::cout << "RValue: " << s << std::endl;
}
 
// 可变参数模板的完美转发
template<typename Func, typename... Args>
auto callFunction(Func&& func, Args&&... args) 
    -> decltype(func(std::forward<Args>(args)...)) {
    return func(std::forward<Args>(args)...);
}
 
// 工厂函数示例
template<typename T, typename... Args>
std::unique_ptr<T> make_unique_custom(Args&&... args) {
    return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
 
int main() {
    std::string str = "hello";
    wrapper(str);              // 转发左值
    wrapper("world");          // 转发右值
    wrapper(std::move(str));   // 转发移动的值
    
    // 使用工厂函数
    auto ptr = make_unique_custom<std::string>("Hello World");
    
    return 0;
}

函数对象和可调用对象

函数指针作为参数

// 函数指针类型
typedef int (*BinaryOp)(int, int);
 
int add(int a, int b) { return a + b; }
int multiply(int a, int b) { return a * b; }
 
void calculate(int x, int y, BinaryOp op) {
    int result = op(x, y);
    std::cout << "Result: " << result << std::endl;
}
 
int main() {
    calculate(5