C++| |Introduction to C++

Getting started with C++


1. Namespace

In c/c++, there are a large number of variables, functions and classes to be learned later. The names of these variables, functions and classes will all exist in the global scope, which may cause a lot of conflicts. The purpose of using namespaces Shi for the name identifier localized to avoid naming conflicts or name contamination , there is the namespace keyword for this problem.

1.1 The definition of namespace

To define a namespace, you need to use the namespace keyword , followed by the name of the namespace , and then a pair of {} is enough, {} is the member of the namespace.

//1.普通的命名空间
namespace N1//N1为命名空间的名称
{
    //命名空间中的内容,既可以是变量,也可以是定义函数
    int a;
    int Add(int left, int right)
    {
        return left + right;
    }
}
​
//2.命名空间可以嵌套
namespace N2
{
    int a;
    int b;
    int Add(int left, int rght)
    {
        return left + right;
    }
    namespace N3
    {
        int c;
        int d;
        int Sub(int left, int right)
        {
            return left - right;
        }
    }
}
​
//3.同一个工程中允许存在多个相同名称的命名空间
//编译器最后会合成同一个命名空间中
​
namespace N1
{
    int Mul(int left, int right)
    {
        return left * right;
    }
}

[Note]: A namespace defines a new scope , and all content in the namespace is limited to that namespace

 

1.2 Use in namespace

How should the members in the namespace be used? such as:

namespace N
{
    int a = 10;
    int b = 20;
    int Add(int left, int right)
    {
        return left + right;
    }
    
    int Sub(int left, int right)
    {
        return left - right;
    }
}
​
int main()
{
    cout << a << endl;//该语句编译出错,无法识别a
    return 0;
}

There are three ways to use namespaces:

  • Add namespace name and scope qualifier

using N::b;
​
int main()
{
    printf("%d\n", N::a);
    return 0;
}
  • Use using to introduce members in the namespace

using N::b;
int main()
{
    cout << N::a << endl;
    cout << b << endl;
    return 0;
}
  • Use namespace name reference

using namespace N;
​
int main()
{
    cout << N::a << endl;
    cout << b << endl;
    Add(10, 20);
    return 0;
}

 

2. C++ input && output

#include <iostream>
using namespace std;
​
int main()
{
    cout << "hello world" << endl;
    return 0;
}

Description:

  1. When using cout standard output (console) and cin standard input (keyboard), you must include the <iostream> header file and the std standard namespace.

  2. It is more convenient to use c++ to output and output, without adding data format control, such as: shaping--%d, character--%c

#include <iostream>
using namespace std;
​
int main()
{
    int a;
    double b;
    char c;
    
    cin >> a;
    cin >> b >> c;
    
    cout << a << endl;
    cout << b << " " << endl;
    
    return 0;
}

 

3. Default parameters

3.1 The concept of default parameters

The default parameter is to specify a default value for the function parameter when declaring or defining the function . When calling this function, if the actual parameter is not specified, the default value is used, otherwise the specified actual parameter is used.

void TestFunc(int a = 3)
{
    cout << a << endl;
}
​
int main()
{
    TestFunc();//没有传参时,使用参数的默认值
    TestFunc(5);//传参时,使用指定的实参
} 

 

3.2 Classification of default parameters

  • All default parameters

void TestFunc(int a = 1, int b = 2, int c = 3)
{
    cout << "全缺省参数" << endl; 
}
  • Semi-default parameters

void TestFunc(int a, int b = 2, int c = 3)
{
    cout << "半缺省参数" << endl;
}

【note】:

  1. The semi-default parameters must be given in order from right to left, and they cannot be given in intervals.

  2. Default parameters cannot appear at the same time as function declaration and definition

//test.h
void TestFunc(int a = 1, int b =2)
{
    
}
​
//test.cpp
void TestFunc(int a = 2, int b = 1)
{
    
}
​
//注意:如果声明和定义位置同时出现,恰巧两个位置提供的值不同,那么编译器就无法确定到底要用那个缺省值
  1. The default value must be a global variable

  2. C language does not support default (compiler does not support)

 

4. Function overloading

4.1 The concept of function overloading

Function overload: It is a special case of functions. C++ allows several functions of the same name with similar functions to be declared in the same scope . The parameter lists (number or type or order of parameters) of these functions with the same name must be different . Deal with the problems of similar functions and different data types.

int Add(int left, int right)
{
    return left + right;
}
​
double Add(double left, double right)
{
    return left + right;
}
​
float Add(float left, double right)
{
    return left + right;
}

 

[Note] : The parameter order can also be overloaded

#include <iostream>
using  namespace std;
​
class Test
{
public:
  void TestFunc(int a, float b)
  {
    cout << "int next float" << endl;
  }
​
  void TestFunc(float a, int b)
  {
    cout << "float next int" << endl;
  }
​
private:
  int _a;
};
​
int main()
{
  Test a;
  a.TestFunc(2, 2.1);
  a.TestFunc(2.1, 2);
  return 0;
}

Output result: int next float float next int

Conclusion: For function overloading , only the number of function parameters, different parameter types, and parameter order can be used for overloading. It is not enough to only have different return values .

 

[Interview Question]: For functions only return values ​​are different, can these two functions be overloaded?

Answer: No, it is determined by the modification of the name of the function.

​ For the C++ compiler at the bottom layer is not the name of the function, but a more complicated name that has been re-modified. The re-modified name contains: the name of the function and the parameter types , which is why the function is overloaded The reason why several functions with the same name require different parameter lists. As long as the parameter list is different , the compiler can re-modify the function name at compile time and include the parameter type in the final name to ensure uniqueness at the bottom .

​ So whether the function can be overloaded is mainly related to the parameter list, not the return value. The return value is only checked during the code run phase, and the parameters are modified during the compilation of the function name

 

4.2 Name modification

In c/c++, a program needs to go through the following stages to run: preprocessing, compilation, assembly, linking

Name Mangling is a mechanism for re- arranging the names of functions and variables during the compilation process . Simply put, in order to distinguish each function, the compiler re-modifies the function to a globally unique name after hearing a certain algorithm .

The C language's name modification rules are very simple, just add an underscore in front of the function name , for example: For the following code, an error will occur at the end of the link.

int Add(int left, int right);
​
int main()
{
    cout << Add(3, 4) << endl;
    return 0;
}

The compiler reported an error : error LNK2019: Unresolved external symbol _Add , which is referenced in function _main .

 

Because C++ needs to support function overloading, namespaces, etc., making its modification rules more complicated , different compilers may have different implementations at the bottom .

For the C++ compiler at the bottom, it is not the name of the function, but a more complicated name that has been re-modified. The re-modified name contains: the name of the function and the parameter types , which is why the function is overloaded Several functions with the same name require different parameter lists. As long as the parameter lists are different , the compiler can re-modify the function name at compile time and include the parameter type in the final name to ensure uniqueness at the bottom .

[Modification rules of function names under linux] :

  • For C++, the function name considers the name and parameters of the function

  • For c, only the name of the function is considered (because the c language does not support function overloading, the modification rules are simple)

//.cpp
int Add(int leftm int right)
{
    
}
​
//修饰:Add(int , int)
//只有函数名字和参数
​
//.c
int Add(int left, int right)
{
    
}
​
//修饰:Add
//只有函数名字

 

[C++ function name modification rules] :

  • The name of the function, parameter type and return value, and namespace are all added to the modified name.

 

5. external "C"

Sometimes in a C++ project, it may be necessary to compile certain functions in the style of C. Add extern "C" before the function , which means to tell the compiler to compile the function according to the C language rules.

extern "C" int Add(int left, int right);
​
int main()
{
    Add(2, 3);
    return 0;
}

An error is reported when linking: error LNK2019: Unresolved external symbol _Add , which is referenced in **function_main

[Interview Questions]:

  1. Can the following two functions be overloaded? Is there a problem? Or under what circumstances will go wrong?

#include <iostream>
using namespace std;
​
class Test
{
public:
  void TestFunc(int a = 9)
  {
    cout << "haveParameter:" << a <<  endl;
  }
​
  void TestFunc(int a)
  {
    cout << "noHaveParameter" << a << endl;
  }
​
private:
  int _a;
};
​
int main()
{
  Test t;
  t.TestFunc(10);
  return 0;
}

Answer: These two functions cannot be overloaded.

​ Non-default functions, function parameters cannot be redeclared

  1. Why doesn't C language support overloading?

Answer: This is because the modification rules for function names are different when compiling.

For c language function name is modified rules are simple, as long as the function name out of the same modified the function name is still the same and independent of the type of parameters, the number of parameters and the name of the function space , and a function name mangling rules of C ++ on the more complex, for a The modification of the function name is not only related to the function name, but also related to the number of function parameters, parameter types, parameter order and name space .

​ So the C language does not support overloading.

  1. How is the bottom layer of function overloading handled in C++?

Answer: The underlying renaming mechanism renames the Add function according to the number of parameters, parameter types, and return value types. Then with function overloading, a function has multiple naming mechanisms. 

In the C++ calling convention (_cdecl calling convention), the Add function is parsed as:

"int __cdecl Add(int,int)" (?Add@@YAHHH@Z)"double __cdecl Add(double,double)" (?Add@@YANNN@Z)

  1. Can a function be compiled in C++ style according to the C language style?

Answer: C++ can add [extern "C"] before the function declaration to make the function compile according to the C language style.

 

6. Citation

6.1 The concept of reference

Reference is not a new definition of a variable, but an alias to an existing variable , the compiler will not open up memory space for the reference variable , it shares the same memory space with the variable it references

Type & reference name (object name) = reference entity ;

Example:

void Test
{
    int a = 10;
    int& ra = a; //定义引用类型
    
    printf("%p\n", &a);
    printf("%p\n", &ra);
}

[Note] : The reference type must be the same type as the reference entity

 

6.2 Reference characteristics

  1. Reference must be initialized when defined

  2. A variable can have multiple references

  3. Once you reference an entity, you can no longer reference other entities

 

6.3 Frequently cited

//常引用
​
#include <iostream>
using namespace std;
​
class Test
{
public:
  void TestFunc()
  {
    const int a = 10;
    //int& ra = a;//编译出错a为常量
    const int& ra = a;//引用类型要匹配
    //int& b = 10; //编译出错b为常量 
  }
};
​
int main()
{
  Test t;
  t.TestFunc();
  return 0;
}

 

6.4 Usage scenarios

  • Make parameters

  • Do return value

What is the output of the following code? why?

//引用返回的局部变量
#include <iostream>
​
using namespace std;
​
class Test
{
public:
  int& Add(int left, int right)
  {
    int c = left + right;
    return c;
  }
};
​
int main()
{
  Test t;
  cout << t.Add(2, 3) << endl;
  return 0;
}

[Note] : If a function returns and leaves, the space on the stack has been returned to the system after leaving the function scope, so the space on the stack cannot be returned as a reference type. If it is returned as a reference type, the period of the return value must not be limited by the function (that is, longer than the life period of the function).

 

6.5 Comparison of the efficiency of passing by value and passing by reference

Use value as a parameter or return value type . During parameter transfer and return, the function does not directly pass the actual parameter or return the variable itself , but passes the actual parameter or returns a temporary copy of the variable , so the value is used as the parameter or The return value type is very inefficient , especially when the parameter or return value type is very large, the efficiency is even lower.

When pointers and references are used as parameters or return value types , the efficiency is almost the same

 

 

6.6 The difference between reference and pointer

  • In terms of grammar , a reference is an alias , there is no independent space , and it shares the same space with its reference entity

  • In the underlying implementation , the reference in fact there is space , because the reference is implemented using pointers in

  • [Comparison of reference and pointer assembly code]

 

[Comparison of reference and pointer] :

  1. Reference definition must be initialized , pointers are not required

  2. A reference cannot refer to another entity after referencing an entity , and a pointer can point to any entity of the same type at any time

  3. No NULL references , but NULL pointers

  4. The meaning in sizeof is different, the result of the reference is the size of the reference type , but the pointer is always the size of the number of bytes occupied by the address space (4 bytes in 32-bit machines)

  5. Adding 1 to the reference is to add 1 to the referenced entity, and adding 1 to the pointer is to offset the size of the type backward

  6. There are multi-level pointers , no multi-level references

  7. The way to access the entity is different , the pointer needs to be explicitly dereferenced , and the reference compiler handles it itself

  8. References are safer to use than pointers

 

7. Range-based for loop (C++11)

7.1 Syntax of range for loop

  • If you want to loop through an array in C++11, you don't need to specify the range of the array, you only need to use a range-based for loop.

  • The content in the parentheses after the for loop is divided into two parts by a colon. The first part is the variable used for iteration, and the second part indicates the scope of the iteration .

Example:

#include <iostream>
​
int main()
{
  int array[10];
  int i = 1;
​
  for (auto& e : array)
  {
    e = i++;   
  }
​
  for (auto e : array)
  {
    std::cout << e << '\n';
  }
​
  return 0;
}

For the for range loop, the principle is to use an iterator, begin, end.

【note】:

  • The for range loop is similar to the normal loop. You can use continue to end this loop, or break to jump out of the entire loop.

 

7.2 Conditions of use for range for

  • The range of for loop iteration must be fixed

    • For arrays, the iteration range is the range between the first element and the last element. For classes, it should provide the iterator methods begin and end. begin and end are the range of loop iteration.

  • The iterated object must implement the operations of ++ and ==

 

8. Use of auto

In the early days of C/C++, auto was used to modify variables. Adding in front of a variable indicates that the variable is an automatic variable . (In fact, it is a local variable)

Automatic variables:

  • When the execution flow enters the function, the variable storage space is automatically allocated, and then when the execution flows out of the function, the storage space of the variable is automatically released.

But in C++11, the keyword has been modified. Auto is no longer a storage type indicator , but has become a new type prompt. The variable declared by auto must be deduced by the compiler at compile time. Type .

【Note】 :

Variables defined using auto must be initialized , otherwise the type of the variable is not known, resulting in errors during compilation . During compilation the compiler needs based on expressions initialization to initialize the actual type of auto .

For auto, it is not a "type declaration", but more a "placeholder" for type declaration . The compiler will replace auto with the actual type of the variable during compilation .

8.1 Auto and pointers and references

For auto conjunction with pointer may not add * , may also be added * .

But it is necessary to add & when auto is used with reference .

 

8.2 Disabling auto

  • Can not use auto as a function parameter to receive the actual parameter of the function

    • Because if auto is used as a formal parameter, the actual parameter is an array for the array, which does not meet the requirements and will cause an error.

  • When using auto to define multiple variables on the same line, the variable types must be the same

    • Because if you define multiple at the same time, just use the type of the first variable to replace auto. If the type of the subsequent variable is inconsistent with the type of the first variable, it will cause an error.

  • auto cannot be used directly to declare arrays

  • For autoC++11, only the usage of auto as a type indicator is reserved.

  • You cannot use auto as a template parameter when instantiating a template.

 

9. nullptr与nullptr_t

Nullptr represents a null pointer constant , and the type of nullptr is nullptr_t

typedef decltype(nullptr) nullptr_t;

【note】:

  • When using nullptr to indicate the null value of a pointer, there is no need to include the header file, because nullptr is introduced according to keywords for C++11

  • In C++11, sizeof(nullptr) and sizeof((void*)0) occupy the same number of bytes

  • In order to improve the robustness of the code, it is best to use nullptr when the pointer is null in the subsequent code.

 

Guess you like

Origin blog.csdn.net/qq_40399012/article/details/84138724