【Introduction to C++】

1. C++ keywords

C++ has a total of 63 keywords, while C language has 32 keywords

Let's take a look at this table

 Some of them are keywords of C language

2. Namespace

If we want to define a variable name that is the same as a library function in C language, can the compiler pass it? Or after we enter the company, when we write the project, when different groups use the same variable name, isn't this a mess?

Don't worry, the namespace is to solve the above problems, so how to solve it? We need to use 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 many conflicts. The purpose of using the namespace is to localize the name of the identifier to avoid naming conflicts or name pollution , and the appearance of the namespace keyword is aimed at this kind of problem.

We can't directly define the library function name in C language

 2.1 Namespace definition

To define a namespace, you need to use the namespace keyword, followed by the name of the namespace, and then a pair of {}, which are members of the namespace .

// 1、正常的命名空间定义
namespace szk
{
	// 命名空间可以定义函数、类型、变量
	int rand = 10;
	int Add(int x, int y)
	{
		return x + y;
	}
	struct student
	{
		char name[20];
		int age;
	};

}
// 2、命名空间可以嵌套定义,
namespace N1
{
	int x, y;
	int Add(int x, int y)
	{
		return x + y;
	}
	namespace N2
	{
		int i, int j;
		int Sub(int i, int j)
		{
			return i - j;
		}
	}
}

// 同一个工程可以同时存在多个重名的命名空间,最后编译器会整合成一个
// text.h
// nemespace N1
// {
//     int x,y;
//     int div(int x,int y)
//     {
//          return x / y;
//     }
// }
// 
// text.c 和 text.h的N1会整合成一个

2.2, the use of namespace

Can it be used directly, the answer is no, it will compile and report an error

 Three ways to use namespaces

1. Add namespace name and specify scope

namespace szk
{
		int a = 10;
		int b = 20;
}

int main()
{
	printf("%d\n", szk::a);
	return 0;
}

2. Use using to introduce a member in the namespace

namespace szk
{
		int a = 10;
		int b = 20;
}

using szk::b;
int main()
{
	printf("%d\n", szk::a);
	printf("%d\n", b);
	return 0;
}

3. Use the using namespace namespace name to import

namespace szk
{
		int a = 10;
		int b = 20;
}

using namespace szk;
int main()
{
	printf("%d\n", a);
	printf("%d\n", b);
	return 0;
}

3. Input and output of C++

#include <iostream>
using namespace std;
int main()
{
	int a = 0;
	cout << "Hello World" << endl;
	cin >> a;
	cout << a << endl;
	return 0;
}

Notice:

1. When using the cout standard output object (console) and the cin standard input object (keyboard), you must include the < iostream > header file and use std according to the usage method of the namespace.

2. cout and cin are global stream objects, and endl is a special C++ symbol that represents newline output. They are all included in the

<iostream> header file.

3. << is a stream insertion operator, >> is a stream extraction operator.

4. It is more convenient to use C++ for input and output, and does not need to manually control the format like printf/scanf input and output. The input and output of C++ can automatically identify the variable type.

5. In fact, cout and cin have many other grammars, such as controlling the input and output of floating-point numbers. Because C++ is compatible with C, not many are used, so I won’t expand here, and there are many documents on the Internet.

Conventions about the std namespace

1. In our daily practice, can we directly expand and directly use using namespace std; Yes, it is very convenient.

2. But when entering a company to do a project, there are many codes and a large scale. If you expand directly, some variable names used will have the same name as library functions. At this time, it is not recommended to expand directly. We can partially expand (expand commonly used ones), or directly specify, for example: std::cout is used like this When specifying the namespace + using std::cout to expand commonly used library objects/types, etc.

4. Default parameters

4.1. Default parameter concept

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

For example:

void Print(int a = 0)
{
	cout << a << endl;
}
int main()
{
	Print();// 没有传参数使用的默认值
	Print(1);// 传了参数,使用实参
	return 0;
}

4.2 Classification of default parameters

1. All default parameters

void Print(int a = 10, int b = 30, int c = 60)
{
    cout << "a = " << a << endl;
    cout << "b = " << b << endl;
    cout << "c = " << c << endl;
}

2. Semi-default parameters

void Print(int a, int b = 30, int c = 60)
{
    cout << "a = " << a << endl;
    cout << "b = " << b << endl;
    cout << "c = " << c << endl;
}

1. Semi-default parameters must be given sequentially from right to left, and cannot be given alternately

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

//a.h
void Print(int a = 10);
​
// a.cpp
void Print(int a = 20)
{
​
}
// 注意:如果生命与定义位置同时出现,恰巧两个位置提供的值不同,
//那编译器就无法确定到底该
//用那个缺省值。

3. The default value must be a constant or a global variable

4. C language does not support (compiler does not support)

5. Function overloading

In natural language, a word has multiple meanings, and people can judge the real meaning of the word according to the context, that is, the word is overloaded.

For example: There used to be a joke that people don't need to watch or worry about two state-owned sports events. One is table tennis and the other is men's soccer. The former is "no one can win!", and the latter is "no one can win!"

5.1 The concept of function overloading

Function overloading : It is a special case of functions. C++ allows several functions with the same name to declare similar functions in the same scope. The formal parameter lists (number of parameters or type or type order ) of these functions with the same name are different, which are often used to deal with Implementing functions is similar to the problem of different data types.

#include<iostream>
using namespace std;
// 1、参数类型不同
int Add(int left, int right)
{
 cout << "int Add(int left, int right)" << endl;
 return left + right;
}
double Add(double left, double right)
{
 cout << "double Add(double left, double right)" << endl;
 return left + right;
}
// 2、参数个数不同
void f()
{
 cout << "f()" << endl;
}
void f(int a)
{
 cout << "f(int a)" << endl;
}
// 3、参数类型顺序不同
void f(int a, char b)
{
 cout << "f(int a,char b)" << endl;
}
void f(char b, int a)
{
 cout << "f(char b, int a)" << endl;
}
int main()
{
 Add(10, 20);
 Add(10.1, 20.2);
 f();
 f(10);
 f(10, 'a');
 f('a', 10);
    
 return 0;
}

5.2 C++ supports the principle of function overloading -- name mangling (name Mangling)

Why does C++ support function overloading, but C language does not support function overloading? In C/C++, for a program to run, it needs to go through the following stages: preprocessing, compiling, assembling, and linking .

 

 1. The actual project is usually composed of multiple header files and multiple source files, and through the compilation link learned in the C language stage, we can know that [when the Add function defined in b.cpp is called in the current a.cpp], After compiling and before linking, there is no function address of Add in the object file of ao, because Add is defined in b.cpp, so the address of Add is in bo. So what to do?

2. So the link stage is dedicated to dealing with this kind of problem. When the linker sees that ao calls Add, but there is no address of Add, it will find the address of Add in the symbol table of bo, and then link them together. (The teacher will take the students to review)

3. When linking, facing the Add function, which name will the linker use to find it? Each compiler here has its own rules for decorating function names.

4. Since the modification rules of VS under Windows are too complicated, and the modification rules of g++ under Linux are simple and easy to understand, we use g++ to demonstrate the modified name below.

5. From the following, we can see that the name of the gcc function remains unchanged after modification. And the modified function of g++ becomes [_Z+function length+function name+type initials]. The result after compiling with a C language compiler

The result after compiling with a C language compiler

 Conclusion: Under linux, after compiling with gcc, the modification of the function name has not changed.

The result after compiling with a C++ compiler

Conclusion: Under Linux, after compiling with g++, the modification of the function name changes, and the compiler adds the function parameter type information to the modified name. 

Name modification rules under Windows

 Comparing Linux, you will find that the VS compiler under Windows has relatively complicated and difficult to understand function name modification rules, but the principles are similar, so we will not do detailed research.

6. Through this, I understand that the C language cannot support overloading, because there is no way to distinguish functions with the same name. C++ is distinguished by function modification rules. As long as the parameters are different, the modified names are different, and overloading is supported.

7. If the function names and parameters of two functions are the same, but the return values ​​are different, it does not constitute overloading, because the compiler has no way to distinguish when calling.

6. Citation

6.1 Reference concepts

A reference is not a new definition of a variable, but an alias for an existing variable. The compiler will not open up memory space for the reference variable, and it shares the same memory space with the variable it refers to.

For example: Lin Chong is called at home , but he is called " Coach Lin " in the world . In fact, the two names are the same person.

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

void TextRef()
{
	int a = 10;
	int& rra = a;
	printf("%p\n", a);
	printf("%p\n", rra);
}
int main()
{
	TextRef();
	return 0;
}

Note: The reference type must be of the same type as the referenced entity

6.2 Citation Properties

1. References must be initialized at definition time

2. A variable can have multiple references

3. Reference Once an entity is referenced, no other entity can be referenced

void TestRef()
{
   int a = 10;
   // int& ra;   // 该条语句编译时会出错
   int& ra = a;
   int& rra = a;
   printf("%p %p %p\n", &a, &ra, &rra);  
}

6.3 Frequent references

void TestConstRef()
{
	const int a = 10;
	//int& rra = a; 该语句编译会报错,a为常量
	const int b = 20;
	//int& rrb = b; 该语句编译会报错,b为常量
	double d = 11.11;
	//int& rdd = d; 该语句编译会报错,引用的类型不同

}

6.4 Usage Scenarios

1. Make parameters

void Swap(int &rra ,int &rrb)
{
	int tmp = rra;
	rra = rrb;
	rrb = tmp;
}

2. Do the return value

int& Add(int a, int b)
{
	static int c = a + b;
	return c;
}
int main()
{
	int& ret = Add(1, 2);
	Add(3, 4);
	cout << "Add(1, 2) is :" << ret << endl;
	return 0;
}

Note: If the function returns out of the scope of the function, if the returned object is still there (not yet returned to the system), you can return by reference, and if it has been returned to the system, you must return by value.

If the above example removes the static, it has to be returned by value, because the variable modified by static is placed in the static area, not on the stack, while the ordinary int c is placed in the stack area, and it will go out of scope. destroyed

6.5 Comparison of pass-by-value and pass-by-reference efficiency

Values ​​are used as parameters or return value types. During parameter passing and return, the function does not directly pass actual parameters or return the variable itself directly, but passes actual parameters or returns a temporary copy of the variable, so values ​​are used as parameters Or the return value type is very inefficient, especially when the parameter or return value type is very large, the efficiency is even lower.

6.5.1 Performance Comparison of Values ​​and References as Return Types


#include <time.h>
struct A { int a[10000]; };
A a;
// 值返回
A TestFunc1() { return a; }
// 引用返回
A& TestFunc2() { return a; }
void TestReturnByRefOrValue()
{
	// 以值作为函数的返回值类型
	size_t begin1 = clock();
	for (size_t i = 0; i < 100000; ++i)
		TestFunc1();
	size_t end1 = clock();
	// 以引用作为函数的返回值类型
	size_t begin2 = clock();
	for (size_t i = 0; i < 100000; ++i)
		TestFunc2();
	size_t end2 = clock();
	// 计算两个函数运算完成之后的时间
	cout << "TestFunc1 time:" << end1 - begin1 << endl;
	cout << "TestFunc2 time:" << end2 - begin2 << endl;
}

int main()
{
	TestReturnByRefOrValue();

	return 0;
}

 6.6 Differences between references and pointers

In terms of syntax, a reference is an alias of the referenced entity, without an independent space, and shares a space with the referenced entity.

int main()
{
int a = 10;
int& ra = a;
cout<<"&a = "<<&a<<endl;
cout<<"&ra = "<<&ra<<endl;
return 0;
}

But in the underlying logic , references are implemented in the form of pointers, which actually have space

int main()
{
int a = 10;
int& ra = a;
ra = 20;
int* pa = &a;
*pa = 20;
return 0;
}

Let's take a look at the comparison of referenced and disassembled code

Differences between references and pointers

1. The pointer can be NULL, but the reference cannot be NULL

2. The use of references is safer than pointers

3. The sizeof calculation value is different, the reference is fixed to the size of the reference entity, and the pointer needs to calculate the size according to different platforms (32-bit is 4)

4. Once a reference refers to an entity, it cannot refer to other entities, and the pointer points to any entity of the same type 

5. There are multi-level pointers, but no multi-level references

6. There are different ways to access entities, pointers need to be dereferenced, and references are processed by the compiler

7. The self-increment of the reference is added by the entity itself, and the self-increment of the pointer is offset by the size of a type

8. A reference is conceptually an alias for a variable, while pointer storage requires an address

9. The reference must be initialized when it is defined, and the pointer is not required

Guess you like

Origin blog.csdn.net/weixin_64214213/article/details/126877093