## Introduction

inline string concatenate(const string& a, const string& b)
{
return a+b;
}


C++ 函数参数是值传递还是引用传递？函数声明中给参数加上 & 是什么操作？参数带 const 又是什么意思？inline 关键字又是干嘛的？

## 参数的值传递和引用传递

Arguments passed by value and by reference

In the functions seen earlier, arguments have always been passed by value. This means that, when calling a function, what is passed to the function are the values of these arguments on the moment of the call, which are copied into the variables represented by the function parameters. For example, take:

nt x=5, y=3, z;


In this case, function addition is passed 5 and 3, which are copies of the values of x and y, respectively. These values (5 and 3) are used to initialize the variables set as parameters in the function's definition, but any modification of these variables within the function has no effect on the values of the variables x and y outside it, because x and y were themselves not passed to the function on the call, but only copies of their values at that moment.

In certain cases, though, it may be useful to access an external variable from within a function. To do that, arguments can be passed by reference, instead of by value. For example, the function duplicate in this code duplicates the value of its three arguments, causing the variables used as arguments to actually be modified by the call:

// passing parameters by reference
#include <iostream>
using namespace std;

void duplicate(int& a, int& b, int& c)
{
a*=2;
b*=2;
c*=2;
}

int main()
{
int x=1, y=3, z=7;
duplicate (x, y, z);
cout << "x=" << x << ", y=" << y << ", z=" << z;
// output: x=2, y=6, z=14
return 0;
}


To gain access to its arguments, the function declares its parameters as references. In C++, references are indicated with an ampersand (&) following the parameter type, as in the parameters taken by duplicate in the example above.

When a variable is passed by reference, what is passed is no longer a copy, but the variable itself, the variable identified by the function parameter, becomes somehow associated with the argument passed to the function, and any modification on their corresponding local variables within the function are reflected in the variables passed as arguments in the call.

In fact, a, b, and c become aliases of the arguments passed on the function call (x, y, and z) and any change on a within the function is actually modifying variable x outside the function. Any change on b modifies y, and any change on c modifies z. That is why when, in the example, function duplicate modifies the values of variables a, b, and c, the values of x, y, and z are affected.

If instead of defining duplicate as:

void duplicate(int& a, int& b, int& c)


Was it to be defined without the ampersand signs as:

void duplicate(int a, int b, int c)


The variables would not be passed by reference, but by value, creating instead copies of their values. In this case, the output of the program would have been the values of x, y, and z without being modified (i.e., 1, 3, and 7).

## 效率考量和常量引用

Efficiency considerations and const references

Calling a function with parameters taken by value causes copies of the values to be made. This is a relatively inexpensive operation for fundamental types such as int, but if the parameter is of a large compound type, it may result on certain overhead. For example, consider the following function:

string concatenate(string a, string b)
{
return a+b;
}


This function takes two strings as parameters (by value), and returns the result of concatenating them. By passing the arguments by value, the function forces a and b to be copies of the arguments passed to the function when it is called. And if these are long strings, it may mean copying large quantities of data just for the function call. But this copy can be avoided altogether if both parameters are made references:

string concatenate(string& a, string& b)
{
return a+b;
}


Arguments by reference do not require a copy. The function operates directly on (aliases of) the strings passed as arguments, and, at most, it might mean the transfer of certain pointers to the function. In this regard, the version of concatenate taking references is more efficient than the version taking values, since it does not need to copy expensive-to-copy strings.

On the flip side, functions with reference parameters are generally perceived as functions that modify the arguments passed, because that is why reference parameters are actually for.

The solution is for the function to guarantee that its reference parameters are not going to be modified by this function. This can be done by qualifying the parameters as constant:

string concatenate(const string& a, const string& b)
{
return a+b;
}


By qualifying them as const, the function is forbidden to modify the values of neither a nor b, but can actually access their values as references (aliases of the arguments), without having to make actual copies of the strings.

Therefore, const references provide functionality similar to passing arguments by value, but with an increased efficiency for parameters of large types. That is why they are extremely popular in C++ for arguments of compound types. Note though, that for most fundamental types, there is no noticeable difference in efficiency, and in some cases, const references may even be less efficient!

## 内联函数

Inline functions

Calling a function generally causes a certain overhead (stacking arguments, jumps, etc...), and thus for very short functions, it may be more efficient to simply insert the code of the function where it is called, instead of performing the process of formally calling a function.

Preceding a function declaration with the inline specifier informs the compiler that inline expansion is preferred over the usual function call mechanism for a specific function. This does not change at all the behavior of a function, but is merely used to suggest the compiler that the code generated by the function body shall be inserted at each point the function is called, instead of being invoked with a regular function call. For example, the concatenate function above may be declared inline as:

inline string concatenate(const string& a, const string& b)
{
return a+b;
}


This informs the compiler that when concatenate is called, the program prefers the function to be expanded inline, instead of performing a regular call. inline is only specified in the function declaration, not when it is called.

Note that most compilers already optimize code to generate inline functions when they see an opportunity to improve efficiency, even if not explicitly marked with the inline specifier. Therefore, this specifier merely indicates the compiler that inline is preferred for this function, although the compiler is free to not inline it, and optimize otherwise. In C++, optimization is a task delegated to the compiler, which is free to generate any code for as long as the resulting behavior is the one specified by the code.

## Recap

C++ 函数参数是值传递还是引用传递？函数声明中给参数加上 & 是什么操作？参数带 const 又是什么意思？inline 关键字又是干嘛的？

1. C++ 没有限定的普通函数和标识符的形式参数的情况下，默认是值传递。也就是在传入实际参数进行函数调用时会进行值拷贝，在函数内部对参数的一些操作并不会影响外部的函数，因为函数调用结束，拷贝的参数也就从帧栈上释放。
2. 通过在函数声明处对函数进行 & 标识符进行限定，对传入的变量转为引用传递，拷贝的仅仅只是参数的单个指针，避免值拷贝造成的内存开销，也能很方便地传入复合数据类型指针。
3. 形式参数带上 const，是因为直接通过 & 标识符传入的参数极有可能在函数体内部被修改，我们想要利用 & 来只传递引用，又不想传入的参数被修改，导致函数对外有副作用，所以给参数加上一个 const，确保函数不能修改传入的参数
4. 那为什么又来个 inline 关键字呢，这是为了给编译器提供一种编译倾向，使得编译器能针对一些短小的函数进行内联展开的编译优化，避免常规函数调用时的帧栈和函数跳转开销

inline string concatenate(const string& a, const string& b)
{
return a+b;
}