[C ++ exploration tour] Part 1 Lesson 8: pass value reference, file source

Source: Internet
Author: User
Tags mathematical functions

[C ++ exploration tour] Part 1 Lesson 8: pass value reference, file source


1. Part 1Lesson 8:Upload value reference, file source

2. Lesson 9 of the first part: array mighty, dynamic and static Integration

Upload value reference, file source

The title of this course is a bit strange. In fact, it is the combination of the key content of this lesson, and you will learn it slowly.


In the last lesson "[C ++ exploration journey], Part 7: function effects, divide and conquer", we first got to know functions.

But don't be too happy. Do you think the function just leaves you like this? How is it possible that a function will survive, as long as you continue programming. Haha, so you cannot run it anymore ~

[I signed an agreement with you. Don't walk out without taking any medicine]

In this lesson, we will continue to learn several knowledge points related to functions. However, we will continue to learn functions in depth. In the future, we will have class, object, and other object-oriented knowledge, and then the function will have another name.

Value Transfer and reference Transfer

Value Transfer

First, we will learn how the operating system manages memory within the function range.

Take the addTwo function as an example. This function is very simple, that is, adding 2 to the parameter and then returning its value. As follows:

int addTwo(int a){ a += 2; return a;}

Do you think a + = 2; is this sentence redundant? You can directly return a + 2; Ah. Next, we will know why this sentence is added here.

Write a applet to test this function:

# Include
Using namespace std; int addTwo (int a) {a + = 2; return a;} int main () {int number (4), result; result = addTwo (number ); cout <"number value:" <number <endl; cout <"after calling the function, the result is:" <result <endl; return 0 ;}

Run this program and output:

The value of number is: 4

After the function is called, the result is: 6.

The most important sentence in the program is, of course

result = addTwo(number);

When the addTwo function is called, many things actually happen:

The program obtains the value of number, which is 4.

An address (like a drawer) in the memory is applied. The label on the drawer is a (name) and the type is int. The value in the drawer is equal to the value of number, which is 4.

The program enters the function body.

Add variable a to 2 and variable a to 6.

The value of a is assigned to the result variable as the return value of the function. The value of result is also changed to 6.

Jump out of the function.

The key point is that the variable number is copied to a new address (New drawer) in the memory, and the label of this new drawer is. We say that parameter a is passed through a value (the value of number is copied to a), which is called a value transfer. When our program is in the addTwo function, the memory conditions are roughly as follows:



Therefore, we use three "Drawers" in the memory ". Note: The number variable is not changed.

Therefore, when operating variable a in the program, it has nothing to do with number, but it only copies the value of number.

Reference Transfer

Our previous course initially introduced the concept of reference. In fact, the reference term is too abstract. Generally, the first time I came into contact with the reference, I thought: Wow, I feel very advanced. In fact, it is not advanced at all. The reference should be more accurately called "alias ".

For example, Xiao Ming is called Xie enming, and some may be called Xiao Ming. James is my alias. Do these two names mean the same person? Yes, they all point to a little naughty, but they are never sloppy in programming technology.

In addition to the previous value transfer method, that is, copying the value of variable number to variable.

Apart from passing values, we also have other methods. You can add a tag named a to the drawer named number in the memory. Equals to an alias for the number variable, called. In this case, the parameter of the function must be referenced. As follows:

Int addTwo (int & a) // Note & this indicates the referenced symbol {a + = 2; return ;}

When we call a function, we do not have to copy that value. The program only gave the number variable an alias. When our program is in the addTwo function, the memory conditions are roughly as follows:



This time, variable a and variable number point to the same memory address (the same drawer). The values in the drawer are 4, and a and number are only two different labels of the drawer. We say that variable a is passed through reference, which is called reference transfer.

The reference is very special. We can see that we didn't allocate a new memory address to the referenced variable a in the memory, which is the memory address of the variable number it references. Therefore, the memory address of the referenced variable is the same as that of the variable it points. Let's test it:

# Include
Using namespace std; int main () {int number (4); int & refNumber = number; cout <"the memory address of the number is:" <& number <endl; cout <"memory address of refNumber is:" <& refNumber <endl; return 0 ;}

Run and output:

As shown in, the variable number has the same memory address as the referenced variable refNumber.

Since value transfer can help us solve the problem, why should we use reference transfer? He Shengliang is born? What are the advantages of reference?

First, we know from the above example that the reference does not need to open a new address in the memory to reduce the overhead.

C language does not reference the concept, but C ++ does. Passing references allows our function addTwo to directly modify parameters. Continue to use the previous test program, but this time in the function parameter is a reference:

# Include
Using namespace std; int addTwo (int & a) {a + = 2; return a;} int main () {int number (4), result; result = addTwo (number); cout <"number value:" <number <endl; cout <"after calling the function, the result is: "<result <endl; return 0 ;}


Run this program and output:


The value of number is 6.

After the function is called, the result is: 6.


Why is the number value changed to 6? In the previous example of value transfer, the value of number remains unchanged.


As we mentioned earlier, the reference is actually an alias. A is an alias of number. They actually point to the same memory address. Therefore, adding 2 to a, that is, adding 2 to number, will change the value of number.


Therefore, be cautious when using the reference, because it will change the referenced object.


For reference, the classic example is the swap function, which is used to exchange the values of two parameters.


# Include
Using namespace std; void swap (double & a, double & B) {double temporary (a); // Save the value of variable a to variable temporary a = B; // Replace the value B = temporary OF a with the value B; // assign the value of temporary to B, that is, replace the value of B with the old value of a} int main () {double a (2.3), B (5.4); cout <"the value of a is" <a <"the value of B is" <B <endl; swap (a, B); // use the swap function cout <"the value of a is" <a <"the value of B is" <B <endl; return 0 ;?}


Run the program and output:


The value of a is 2.3. The value of B is 5.4.

The value of a is 5.4. The value of B is 2.3.


We can see that the values of the two variables a and B are exchanged.


If we do not need to transmit references, but use traditional values, then we only need to copy the variables, not the variables themselves.


For the moment, the concept of reference may be somewhat abstract to everyone, but don't worry. We will often use reference in subsequent courses. There are still many things to say about reference, it's just a coincidence.


After that, I learned the pointer chapter and explained the similarities and differences between references and pointers.


Reference transfer that cannot be rewritten


Since the reference is mentioned, we need to introduce the common usage of a reference. This usage will be useful in the next course. Let's take a look at it first.


We can say that there is an advantage in reference transfer over value transfer: No copy is made.


Imagine if I have a function, one of which is a string type string. Assume that the content in your string variable is a long string, for example, there are so many characters in a small book. Therefore, the overhead of copying such a long string is very time-consuming, even if the copy is in the memory. This copy is completely meaningless, so we should avoid using the value transfer method.


Of course, you will proudly say to me: we can use references for transmission. Yes, good idea. If you use references for transmission, you do not need to copy them. However, there is a small defect in passing a reference: you can modify the object to which it points. However, this cannot be said to be a defect. After all, it is also useful to reference it.


Void f1 (string text); // time-consuming copy {}
Void f2 (string & text); // do not copy. The function can directly modify the value of the string variable {}


The solution is to use a reference that cannot be rewritten for transfer.


In the previous course, we introduced the const keyword. The variable modified by it becomes an unchangeable variable.


We use references to avoid copying, and use the const variable to modify the reference so that the reference cannot be modified.


Void f1 (string const & text); // the value of the string variable cannot be modified without copying {}


At present, this method does not seem to be of great use to us, but the second part of this course will learn Object-Oriented Programming and will often use this technology.


Reasonable Arrangement of header files and source files


When we introduced functions in the previous lesson, we have already said that functions are used to reuse (reuse) the "Bricks" (code blocks) that have been created ).


Currently, we have learned how to create custom functions, but these functions are still in the same file as the main function. We have not really reused them.


Like C, C ++ allows us to split programs into different source files. In these source files, we can define our own functions.


When these functions are used, the content of the file is introduced. In this way, our functions can be used for different projects. In this way, we can truly reuse these split bricks to build houses.


Necessary files


But in order to better organize the program, the computer pioneers used two types of files, instead of one (why "let alone", you will know after learning ):


  1. Source file: it ends with. cpp (it can also end with. cc,. cxx,. C) and contains the specific source code of the function.

    Header file: it ends with. h (it can also end with. hxx,. hpp) and contains the description of the function. It is called the prototype of the function ).


    Now, why is there a "file source" in the title of this lesson? Is the finger file and source file.


    Let's take the addTwo function as an example to create the source file and header file respectively.


    int addTwo(int number){ int value(number + 2); return value;}


    We will use the CodeBlocks IDE (integrated development environment) for demonstration. If you use a text editor (such as Vim, Emacs, Sublime, and so on) and gcc (compiler) to write and compile code, you can simply create a file.


    In addition, by default, your Codeblocks C ++ project has been created, that is, a project with its own main. cpp file has been created, and the name can be obtained at will.


    For example:



    We just demonstrate how to create the function's source file and header file.


    Source File


    First, open the menu bar in the following order: File> New> File.



    Then select C/C ++ source in the following window:



    Then, click Go. Window:



    Select C ++ and click Next. Enter the following window:



    Enter the complete path of the source file to be created (select a directory and enter the file name ). We select the directory of the file as the same directory as main. cpp.


    The file name should be as accurate as possible. Do not use 1.cpp. you will not know what the file is doing in the future.


    Math. cpp is used in our demonstration. Because our addTwo function performs mathematical operations, it is named by math (abbreviation of mathematics.


    Then you can select both Debug and Release.


    Click Finish. You have created the source file. Next we will create the header file.


    Header file


    The source file is the same as the source file. Choose File> New> File, and select C/C ++ header in the window:



    Click Go to the next step:



    It is recommended that the header file name be the same as the source file name, but the suffix name is different.


    The header file is also placed in the same directory as main. cpp. The math_h_marshded is automatically generated and does not need to be modified.


    Click Finish. You have created your header file.


    Once both the source file and header file are created, your project should be similar to this:



    Now that the file is ready, we need to fill in the content to define our function.


    Complete source file


    As mentioned before, the source file contains the specific definition of the function. This is one point.


    In addition, it is a little more complex to understand: the compiler needs to know that there is a connection between the source file and the header file.


    Currently, our source file is empty. First, we need to add such a line to it:


    #include "math.h"


    You should be familiar with the format of this line of code, as we have said before.




    This line of familiar code is used to introduce the standard iostream library of C ++.


    Then, # include "math. h" is to introduce the content defined in the math. h file.


    However, why is the header file of the C ++ standard library included in angle brackets, and the math. h We define is included in double quotation marks?


    C ++ has some compiled header files (such as standard function libraries), which are stored in the include folder of the system. When we use the # include <File Name> command, the compiler will find the corresponding file in this folder.


    Obviously, an error occurs when we use this method to include a self-compiled header file (not in the system include folder.


    Therefore, parentheses should be used when the header file provided by C ++ is included.


    On the contrary, the # include "file name" command First searches the directory where the current file is located for matching files. If the file is not found in the system include folder.


    Now let's complete the math. cpp content, which is actually very simple, as follows:


    #include "math.h"int addTwo(int number){ int value(number + 2); return value;}


    Complete header file


    We can see that the initial content of the math. h header file is not empty. But:



    What do these commands mean?


    They are designed to prevent the compiler from repeatedly introducing this header file. The compiler is not always so intelligent and may introduce the same header file cyclically.


    As mentioned above, the header file contains the prototype of the function. We need to write the prototype between the second sentence and the third sentence, as shown below:


    #ifndef MATH_H_INCLUDED#define MATH_H_INCLUDEDint addTwo(int number);#endif // MATH_H_INCLUDED


    How can the preceding three statements starting with # prevent repeated introduction of header file content?


    These statements are called Conditional compilation statements.


    First, if the header file is introduced for the first time, the first command will be read:


    #ifndef MATH_H_INCLUDED


    Ifndef is short for if not defined, indicating "if not defined ". The entire sentence indicates that math_h_1_ded is not defined.


    If this header file is introduced for the first time, math_h_1_ded is not defined yet. # Ifndef MATH_H_INCLUDED is set up.


    Therefore, enter the Conditional compilation statement and execute # define MATH_H_INCLUDED. The definition (define is the meaning of "Definition" in English) math_h_1_ded.


    Then introduce


    Int addTwo (int number );


    Finally, the third condition Compilation instruction comes:


    #endif // MATH_H_INCLUDED


    Endif is the abbreviation of end if, indicating "end if condition compilation". The // math_h_encoded ded is a comment and will be ignored by the compiler.


    Then, if we introduce this header file, the compiler reads the first conditional Compilation instruction,


    # Ifndef MATH_H_INCLUDED


    It is found that math_h_1_ded has been defined before, so # ifndef math_h_1_ded is not valid. Therefore, it does not enter the Conditional compilation statement. Directly jump out. Will not be introduced again


    int addTwo(int number);


    . It's amazing.


    Of course, we use an IDE such as CodeBlocks, which automatically generates the three Conditional compilation commands. If we use a text editor, these three statements are not automatically generated. We need to write it manually.


    Math_h_encoded ded can be changed to any other text. You only need to ensure that the text in the three conditional commands is the same, but ensure that no two header files use the same text.


    Note. The above function prototype is actually the first line defined by the function in the source file, but it does not have the function body included in braces, and a semicolon is added after the parameter list.


    The preceding example shows a simple case where the function parameter is of the common variable type. Suppose we want to use a type such as string. The header file may be changed as follows:


    #ifndef MESSAGE_H_INCLUDED#define MESSAGE_H_INCLUDED#include 
        void displayMessage(std::string message);#endif // MESSAGE_H_INCLUDED


    You can see that you need to add # include before the function prototype. This command indicates that the header file of the string C ++ standard library will be introduced. In addition, std: Must be added before the string type in the parameter list ::




    Remember that we didn't add std: Before using cout and cin?


    That's because we are using cout. Before cin, we already use


    using namespace std;


    Indicates the use of the std namespace (for namespaces, subsequent courses will learn ).


    Because cout and cin are in the namespace std, std ::


    However, the header file does not contain the using namespace std; command (we do not recommend placing using namespace std; in the header file to the source file ), therefore, we need to add std: Before the string, because the string is also located in the std namespace.


    Now, let's test the addTwo function.


    We only need. add a line in cpp # include "math. h ", indicating the introduction of math. h header file, which is defined in math. cpp, but because of math. # include "math. h ", so in main. do not specify math in cpp. cpp. (Whether it is dizzy ...)


    # Include
    # Include "math. h "using namespace std; int main () {int a (2), B (3); cout <" the value of a is: "<a <endl; cout <"B value:" <B <endl; B = addTwo (a); // function call cout <"the value of a is: "<a <endl; cout <" B value: "<B <endl; return 0 ;}


    Run, display:


    The value of a is 2.

    The value of B is 3.

    The value of a is 2.

    The value of B is: 4



    Now, we have truly stored reusable bricks separately. If you want to use the addTwo function in another project, you just need to copy the two files math. h and math. cpp. Then write # include "math. h file path/math. h" in the source file to be used"


    You can also define multiple functions in the same file. In general, we will put the same class of functions in the same file, such as those mathematical functions in one file, those functions used to display menus in another file, and so on.


    Programming requires organization and planning.


    A good comment is half of the Code


    It is annoying to see that the code in a large project is not very annotated, especially for projects developed by many people. The naming rules and programming style are different. If there is no comment, it looks quite tired.


    Generally, programmers who do not write comments are not good programmers. They only write their own code well and do not care whether the Later users are killed on the beach by their code. It should be dragged out to rub your face for five minutes (what is the penalty for being cute? The picture is so beautiful that I dare not look at it ):



    Writing comments is particularly useful for functions. Because you may use functions written by other programmers. If you already have comments on functions, you generally do not need to read all the code of the function (programmers will be "lazy ).


    For a function, our comments generally include three aspects:

    • Functions

      Parameter List

      Return Value


      Let's write a comment for the addTwo function:


      # Ifndef MATH_H_INCLUDED # define MATH_H_INCLUDED/** add 2 operation to the parameter *-number: number of operations to be added 2 * return value: number + 2 */int addTwo (int number); # endif // math_h_1_ded


      The format of writing comments varies with your personal interests. Regardless of the commonly used annotation format (doxygen format ):


      /*** \ Brief add 2 operations to the parameter * \ param number the number of operations to add 2 * \ return number + 2 */int addTwo (int number );


      Default Value of the Parameter


      We have learned about the function parameters. If a function has three parameters, we need to provide the value of these three parameters to the function so that the function can be called normally.


      However, this is not necessarily true. The following functions are used to learn the usage of default function parameters:


      int secondNumber(int hours, int minutes, int seconds){ int total = 0; total = hours * 60 * 60; total += minutes * 60; total += seconds; return total;}


      This function is used to calculate the total number of seconds based on the given hours, minutes, and seconds. Very easy to understand.


      Therefore, hours, minutes, And seconds are three parameters of the secondNumber function. When a function is called, we need to set values for the three parameters.



      We have learned this before.


      Default Value


      To learn new knowledge, we can specify the default value for the function parameters. If these parameters are not specified when the function is called, the default value is used.


      First, we can see that no default value is specified:


      # Include
      Using namespace std; // function prototype int secondNumber (int hours, int minutes, int seconds); // main function int main () {cout <secondNumber (1, 10, 25) <endl; return 0;} // Function Definition int secondNumber (int hours, int minutes, int seconds) {int total = 0; total = hours * 60*60; total + = minutes * 60; total + = seconds; return total ;}


      Run, display:




      Because 1 hour equals 3600 seconds, 10 minutes equals 600 seconds, and 25 seconds equals... 25 seconds. So 3600 + 600 + 25 = 4225


      Now, let's set some parameters of the secondNumber function as parameters with default values. For example, the default values of minutes and seconds in minutes are 0, because we usually use more than one hour, and only the hours are used.


      We need to rewrite the function prototype as follows:


      int secondNumber(int hours, int minutes = 0, int seconds = 0);


      Have you seen it? There are more after minutes and seconds.


      = 0


      This is the default parameter value of the function. Set this parameter to 0. The test is as follows:


      # Include
      Using namespace std; // function prototype int secondNumber (int hours, int minutes = 0, int seconds = 0); // main function int main () {cout <secondNumber (1) <endl; return 0;} // function definition. The default value of int secondNumber (int hours, int minutes, int seconds) is not written) {int total = 0; total = hours * 60*60; total + = minutes * 60; total + = seconds; return total ;}


      Run, display:




      This is because hours is 1, and minutes and seconds are not specified. The default value is 0. 1 hour equals 3600 seconds.


      Note: The default values of function parameters can only be written in the function prototype. If they are written in the function definition, the compiler reports an error.


      Assume that:


      cout << secondNumber(1,10) << endl;






      Because hours is 1, minutes is 10, and seconds is not specified, the default value is 0.


      So 3600 + 600 = 4200


      Special Cases


      When using the default parameters of a function, there may be many situations, some of which are special. For example, we can use the secondNumber function as an example ):


      1. If I have specified the hours and seconds values but the minutes values are not specified, what should I do?


      You cannot use the following format:


      cout << secondNumber(1,,25) << endl;


      This will cause errors. In C ++, we cannot skip a parameter, even if it has a default value. If we assign a value to the start and end parameters, the intermediate parameters also need to be assigned a value.


      You still have to write it like this:


      cout << secondNumber(1, 0, 25) << endl;


      2. Can this be written?


      int secondNumber(int hours = 0, int minutes, int seconds);


      No. An error occurs. Because the default value of the parameter must be written by right. That is to say, if only the hours parameter has a default value, you must write the hours parameter to the rightmost, as shown below:


      int secondNumber(int minutes, int seconds, int hours = 0);


      In this way, there will be no errors.


      3. Can I set all parameters to default values?


      Yes. Example:


      int secondNumber(int hours = 0, int minutes = 0, int seconds = 0);cout << secondNumber() << endl;


      The output is 0.


      Set two main rules for default parameters


      1. Only the function prototype can contain the default values of parameters.

        The default value of a parameter is written after the parameter list. It is written on the right side.




        1. A function can receive data (through parameters) or return data (through the retur function, you can receive references as parameters to directly modify information in the memory.

          We recommend that you classify your programs into different files as the number of programs increases. A specific function is stored in each file, and the file is organized in pairs:. cpp file storage function definition,. h file storage function prototype.

          Be sure to write the comments.


          Part 1 Lesson 9 advance notice


          Today's class is here. Come on!

          In the next lesson, we will learn:Array mighty, combination of dynamic and static

    Related Article

    Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.