[C++] Initial C++ (1)

Table of contents

0 Preface 

1 C++ keywords (C++98)

2 namespace

2.1 Definition of Namespace

2.2 Use of Namespaces (Authorization) 

2.2.1 Direct use 

2.2.2 Partial Expansion (Authorization)

2.2.3 Expand All (Authorization)

3 C++ input & output

4 Default parameters

4.1 Default parameter concept

4.2 Classification of default parameters

5 function overloading

6 references

6.1 Reference concept

6.2 Citation Properties

6.3 Reference usage scenarios

6.3.1 Making parameters

6.3.2 Do return value

6.4 The difference between references and pointers


0 Preface 

C++ is a powerful programming language that has been expanded and upgraded by adding object-oriented programming ideas to the C language.

C language is a structured and modular language, suitable for handling smaller-scale programs. For complex problems and large-scale programs that require a high degree of abstraction and modeling, C language is not suitable. In order to solve the software crisis, in the 1980s, the computer industry proposed the idea of ​​OOP (object oriented programming: object-oriented), and programming languages ​​supporting object-oriented programming emerged as the times require.

In 1982, Dr. Bjarne Stroustrup introduced and expanded the concept of object-oriented on the basis of C language, and invented a new programming language. In order to express the origin relationship between the language and the C language, it is named C++. Therefore: C++ is produced based on the C language. It can not only carry out the procedural programming of the C language, but also carry out object-based programming characterized by abstract data types, and can also carry out object-oriented programming. It is precisely because of this background that C++ is fully compatible with the grammar of C language, and all grammars of C language are applicable in C++.

C++ can not only carry out procedural programming of C language, but also carry out object-based programming characterized by abstract data types, and can also carry out object-oriented programming characterized by inheritance and polymorphism. While C++ is good at object-oriented programming, it can also perform process-based programming. C++ can create almost any type of program: games, device drivers, cloud, desktop, embedded and mobile applications, and more. Even libraries and compilers for other programming languages ​​are written in C++.

1 C++ keywords (C++98)

C++ has a total of 63 keywords compared to 32 keywords in C language.

The following is a list of C++ keywords

asm do if return try continue
auto double inline short typedef for
bool dynamic_cast int signed typeid public
break else long sizeof typename throw
case enum mutable static union wchar_t
catch explicit namespace static_cast unsigned default
char export new struct using friend
class extern operator switch virtual register
const false private template void true
const_cast float protected this volatile while
delete goto reinterpret_cast

2 namespace

First look at the following C language program:

#include <stdio.h>
#include <stdlib.h>
int rand = 10;
int main()
{
    printf("%d\n", rand);
    return 0;
}

This code cannot be run through, the compiler will directly report an error: error C2365: “rand”: redefinition; this is because there is a function called rand in stdlib.h, and a global variable rand is defined, This will lead to the problem of redefinition, and the C language cannot solve this problem.

In C/C++, there are a large number of variables, functions, and C++ classes. 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. The appearance of the namespace keyword is aimed at this kind of problem.

2.1 Definition of Namespace

To define a namespace, you need to use the namespace keyword, followed by the name of the namespace. You can choose the name according to your preference, and then connect a pair of {}, which are members of the namespace. Variables, types, and functions can be defined in a namespace, and namespaces support nested definitions.
like:

namespace mj
{
	//命名空间中可以定义变量/函数/类型
	int r = 10;

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

	struct Node
	{
		struct Node* next;
		int val;
	};

	namespace xxx
	{
		int r = 1;
	}
}

ps: Multiple namespaces with the same name are allowed in the same project, and the compiler will finally synthesize them into the same namespace.

A namespace defines a new scope , and everything in the namespace is confined to that namespace.

2.2 Use of Namespaces (Authorization) 

A namespace can be regarded as a closed space with high permissions, and it cannot be used normally without expanding (authorizing) its members.

Here we need to introduce a new keyword using to help us use the namespace. Here are three ways to use it:

2.2.1 Direct use 

A new operator needs to be introduced here: the scope qualifier::

Use as  namespace-name::namespace-member  .

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

2.2.2 Partial Expansion (Authorization)

If we only need to use some members of the namespace, then we can use partial expansion (authorization). By using namespace-name::namespace-member-name .

Taking mj above as an example, the usage method is as follows:

//部分展开(授权)
using mj::Add;
using mj::r;

int main()
{
	printf("%d\n",r);
	printf("%d\n", Add(1, 2));
	return 0;
}

2.2.3 Expand All (Authorization)

Expand all is to directly expand all members in the namespace through the using keyword, and expand in the way of  using namespace namespace name , such as:

using namespace mj;

3 C++ input & output

C++ has many standard libraries. Just like the input and output functions of C language are included in stdio.h, the standard input and output stream of C++ is iostream.

#include <iostream>

//std是c++标准库的命名空间
using namespace std;
int main()
{
	int i;
	double j;
	//>>流提取运算符
	cin >> i >> j;

	//<<流插入运算符
	cout << i << ' ';
	cout << j << endl;
	return 0;
}

Note:
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 means newline output. They are all included in the
header file containing <iostream>.
3. << is a stream insertion operator and >> 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 are objects of type ostream and istream respectively. >> and << also involve operator overloading and other knowledge. We will learn this knowledge
later, so we just simply learn how to use them here. Later, I will learn more about the usage and principle of IO flow 

Note: In the early standard library, all functions were implemented in the global domain, declared in the header file with the
suffix of . , and in order to correctly use the namespace,
it is stipulated that the C++ header file does not contain .h; the old compiler (vc 6.0) also supports the <iostream.h> format, and the subsequent compiler does not support it,
so use <iostream>+std The way.

std is the namespace of the C++ standard library, and the expansion of std is standardized:

1. In daily practice, it is recommended to directly use namespace std, which is very convenient.
2. When using namespace std is expanded, the standard library is fully exposed. If we define a type/object
/function with the same name as the library, there will be conflicts. This problem rarely occurs in daily practice, but
it is easy to occur when there are many codes and large scale in project development. Therefore, it is recommended to use it in project development, specifying the namespace +
using std::cout to expand common library objects/types when using it like std::cout.

4 Default parameters

4.1 Default parameter concept

C++ supports default parameters, which is one of the differences between C++ and C language.

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

As in the following program, the output results are 0 and 10 respectively

void Func(int a = 0)
{
    cout<<a<<endl;
}
int main()
{
    Func(); // 没有传参时,使用参数的默认值
    Func(10); // 传参时,使用指定的实参
    return 0;
}

It can be seen from the above program that the default parameter is actually to assign an initial default value to the formal parameter when the function is defined. If no parameter is passed for this parameter when the function is called, then the default value is used.

4.2 Classification of default parameters

Default parameters are divided into full default and semi-default. 

  • All default parameters
    void Func(int a = 10, int b = 20, int c = 30)
    {
        cout<<"a = "<<a<<endl;
        cout<<"b = "<<b<<endl;
        cout<<"c = "<<c<<endl;
    }
    int main()
    {
    	Func();
    
    	// 显示传参,从左往右显示传参
    	Func(1);
    	Func(1,2);
    	Func(1, 2, 3);
    
    	return 0;
    }

    All default parameters mean that all the parameters in the function are default parameters, and the parameter passing rule is to pass parameters sequentially from left to right. Those without parameters are processed with default values.

  • semi-default parameter
    void Func(int a, int b = 10, int c = 20)
    {
        cout<<"a = "<<a<<endl;
        cout<<"b = "<<b<<endl;
        cout<<"c = "<<c<<endl;
    }

    Special attention is required here:

    1. The 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, because if life and definition appear at the same time, and the values ​​provided by the two positions are different, then the compiler cannot determine which default value should be used.

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

5 function overloading

Function overloading is a special case of functions. C++ allows several functions of the same name with similar functions to be declared in the same scope. These functions with the same name have different formal parameter lists (number of parameters or type or type order), which are often used to deal with implementation . The function is similar to the problem of different data types.

You can experience C++ function overloading through the following program:

#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;
}

operation result:

Note: If the number of function parameters is the same, the type is the same, and the order is the same, but the return value type of the function is different, it cannot constitute function overloading. For example the following program:

int f(double a, int b)
{
    cout << "int f(double , int b)" << endl;
    return 0;
}
void f(double a, int b)
{
    cout << "void f(double , int b)" << endl;
}

Suppose we call f(1.1 , 1 ), at this time the compiler does not know which of the above two functions will be called, which will cause ambiguity. So this situation cannot constitute function overloading.

6 references

6.1 Reference concept

Reference is an upgrade of C++ based on C language. 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, a person can have multiple code names. We can refer to a person by a first name, and we can refer to a person by other nicknames. Whether it is by name or nickname, it refers to the same person. In other words, a reference in C++ means that there are multiple names for the same variable, and all the names point to the same thing.

The format of the reference is: type & reference variable name (object name) = reference entity;

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

The above program is a simple example of reference, ra and a are equivalent, they both represent the same space in the memory. Note: The reference type must be of the same type as the referenced entity

6.2 Citation Properties

References have three important properties:

  1. The reference must be initialized when it is defined, otherwise the compiler will report an error;
  2. A variable can have multiple references;
  3. Once a reference refers to an entity, it cannot refer to another entity.

6.3 Reference usage scenarios

References generally have two common usage scenarios: as parameters and as return values.

6.3.1 Making parameters

When a reference is used as a parameter, the type needs to be declared in the function parameter.

In general, if a function needs to use pointers, it can be changed to use references, which will be more convenient.

Taking the classic exchange function as an example, the following is the C language version:

void Swap(int* left, int* right)
{
    int temp = *left;
    *left = *right;
    *right = temp;
}

Here is the C++ version: 

void Swap(int& left, int& right)
{
    int temp = left;
    left = right;
    right = temp;
}

Since the reference variable is an alias of the original variable, the modification of the reference variable is equivalent to the modification of the original variable. For the C language that does not support references, the exchange of two variables needs to be called by address, which is essentially a method of passing parameters by value ; while the C++ method is called passing parameters by reference, which greatly increases the readability of the code and is convenient. the designer.

Passing by reference is more efficient than passing by value. So we can summarize the two advantages of passing parameters by reference:

  1. Improve efficiency;
  2. It is more convenient to deal with output parameters (modification of formal parameters affects actual parameters)

6.3.2 Do return value

Let's look at the following program first:

int Add(int a, int b)
{
    int c = a + b;
    return c;
}
int main()
{
    int ret = Add(1, 2);
    return 0;
}

For this program, the function Add should return 3, but the return here does not directly return c to ret, because after the function is out of scope, the function stack frame will be destroyed, that is, the space pointed to by c will be looked back. At this point the object pointed to by c is unknown. Therefore, the compiler creates a temporary variable, copies the value of c to this temporary variable, and then assigns the value of the temporary variable to ret. This is the correct logic for return by value .

The pass-by-reference return codes are as follows:

int& Add(int a, int b)
{
    int c = a + b;
    return c;
}
int main()
{
    int ret = Add(1, 2);
    return 0;
}

Returning by reference is like this: on the basis of the original function type, the type is rewritten as a reference type. As in the above code, what the function finally returns at this time is not c, but an alias of c.

However, this way of writing is problematic. Taking the above code as an example, after the function stack frame is destroyed, even if we get the alias of c and assign it to ret, we can find the space referred to by c through ret. But after the stack frame is destroyed, the space originally referred to by c has been reclaimed. At this time, accessing through ret will form a situation similar to a wild pointer. Therefore, it is inappropriate to use return by reference in this case, and return by value should be used.

However, if we can ensure that the original object is not affected after leaving the scope of the function, we can use pass-by-reference to improve efficiency. Let's take the modification of the sequence table as an example:

C language version:

struct SeqList
{
	int a[10];
	int size;
};
 /*C的接口设计
 读取第i个位置的值*/
int SLAT(struct SeqList* ps, int i)
{
	assert(i < ps->size);
	// ...
	return ps->a[i];
}
 //修改第i个位置的值
void SLModify(struct SeqList* ps, int i, int x)
{
	assert(i < ps->size);

	// ...
	ps->a[i] = x;
}
int main()
{
	struct SeqList s;
	s.size = 3;
	// ...
	SLModify(&s, 0, 10);
	SLModify(&s, 1, 20);
	SLModify(&s, 2, 30);
	cout << SLAT(&s, 0) << endl;
	cout << SLAT(&s, 1) << endl;
	cout << SLAT(&s, 2) << endl;

	return 0;
}

C++ version:

int& SLAT(struct SeqList& ps, int i)
{
	assert(i < ps.size);
	// ...
	return (ps.a[i]);
}

int main()
{
	struct SeqList s;
	s.size = 3;
	// ...
	SLAT(s, 0) = 10;
	SLAT(s, 1) = 20;
	SLAT(s, 2) = 30;
	cout << SLAT(s, 0) << endl;
	cout << SLAT(s, 1) << endl;
	cout << SLAT(s, 2) << endl;

	return 0;
}

Because for the sequence table, its array space is defined globally, and it will not be modified after it goes out of the scope of the function, so you can use the method of return by reference to directly modify the returned object, so that a Modify function can be omitted the design of.

In summary, we can conclude that there are two advantages of return by reference:

  1. Improve efficiency;
  2. You can directly modify the returned object

At the same time, return by reference also has a flaw, that is, it can only be used if the original object is still in the scope of the function (that is, the occupied memory space has not been modified), otherwise it will cause an unsafe situation like a wild pointer.

6.4 The difference between references and pointers

References and pointers have the following differences:

  1. A reference conceptually defines an alias for a variable, and a pointer stores the address of a variable.
  2. References must be initialized when they are defined, pointers are not required
  3. After the reference refers to an entity during initialization, it cannot refer to other entities, and the pointer can point to any entity of the same type at any time
  4. There are no NULL references, but there are NULL pointers
  5. The meaning is different in sizeof: the reference result is the size of the reference type, but the pointer is always the number of bytes occupied by the address space (4 bytes under the 32-bit platform)
  6. The self-increment of the reference means that the referenced entity increases by 1, and the self-increment of the pointer means that the pointer offsets the size of a type backward
  7. Multi-level pointers, but no multi-level references
  8. There are different ways to access entities, the pointer needs to be explicitly dereferenced, and the reference compiler handles it by itself
  9. References are relatively safer to use than pointers

Guess you like

Origin blog.csdn.net/fbzhl/article/details/131893785