Hello, everybody. In the last few days, I summarized some contents of the written test interview last autumn, and re-planned the classification. It is divided into resume writing, interview skills, face summary, written test interview eight-part summary and other four parts.

Among them, the eight-part paper is divided into C/C++, data structure and algorithm analysis, ARM system and architecture, Linux driver development, operating system, network programming, famous enterprise written test questions and other seven parts. This eight-part article update, for part of the inappropriate content was deleted, and C++ related content was added.

The content of the above seven parts, will be an update in the making, links to https://github.com/ZhongYi-Li… . I hope you can give me a STAR support, so that I have the power to continue to update. When all the content is updated, it will be consolidated into a PDF. Without further ado, look at the table of contents.

Warning: this article content is very long, very long, very long! If you don’t have the patience to read all the suggestions, jump directly to GitHub and get a PDF download.

C/C++

The keyword

The use of “# “and “# #” in C macros

  1. (#) String operator

Effect: Converts the incoming parameter name in a macro definition to a string of parameter names enclosed in double quotation marks. It can only be used in macro definitions with passed parameters and must precede the parameter name in the body of the macro definition.

Such as:

#define example1(instr) #define example1(instr) #define example1(instr) #define example1(instr) #define example1(instr)
example( abc ); // 在编译时将会展开成:printf("the input string is:\t%s\n","abc")
string str = example1( abc );  // 将会展成:string str="abc"
  1. The (##) symbolic concatenation operator

Function: Converts multiple parameters defined by a macro to a single actual parameter name.

Such as:

#define exampleNum( n )  num##n

Use:

int num9 = 9; int num = exampleNum( 9 ); // int num = num9

Note:

A. Spaces before and after ## are optional when concatenating parameters with ##.

Such as:

#define exampleNum(n) num##n

B. The actual parameter name after the connection must be defined by an actual parameter name or a macro known to the compiler.

C. ## will prevent macro expansion if the parameter after ## is itself a macro.

#include <stdio.h> #include <string.h> #define STRCPY(a, b) strcpy(a ## _p, #b) int main() { char var1_p[20]; char var2_p[30]; strcpy(var1_p, "aaaa"); strcpy(var2_p, "bbbb"); STRCPY(var1, var2); STRCPY(var2, var1); printf("var1 = %s\n", var1_p); printf("var2 = %s\n", var2_p); //STRCPY(STRCPY(var1,var2),var2); Strcpy (strcpy(var1_p,"var2")_p,"var2 "); strcpy(var1_p,"var2")_p,"var2 "); Strcpy (strcpy(var1,var2)_p,"var2") strcpy(var1,var2)_p,"var2") Implicit declaration of function 'STRCPY' return 0; // Implicit declaration of function 'STRCPY' return 0; }

Results:

var1 = var2
var2 = var1

What does the keyword volatile mean? Give three different examples, right?

  1. Hardware registers for parallel devices. Memory mapped hardware registers are usually volatile because registers can be modified by peripheral hardware at any time. Always use volatile when declaring a pointer to a device register, which tells the compiler not to make assumptions about data stored at that address.
  2. A variable modified in an interrupt service routine for detection by another program. Volatile reminds the compiler that variables defined after it are subject to change at any time. Therefore, every time the compiled program needs to store or read the variable, it will read the data directly from the variable address. Without the volatile keyword, the compiler might optimize reading and storage, perhaps temporarily using the value in the register, and inconsistencies might occur if the variable was updated by another program.
  3. A variable shared by several tasks in a multithreaded application. Simply prevent the compiler from optimizing the code. For example, the following program:
XBYTE[2]=0x55;
XBYTE[2]=0x56;
XBYTE[2]=0x57;
XBYTE[2]=0x58;

To external hardware, each of the four statements represents a different operation, resulting in four different actions, but the compiler optimizes the four statements to assume that only Xbyte [2]=0x58 (that is, ignores the first three statements and produces only one machine code). If volatile is typed, the compiler compiles it one by one and generates the corresponding machine code (producing four pieces of code).

What is the function of the keyword static?

  1. In the body of a function, it is initialized only once, and a variable declared static holds its value for the duration of the call.
  2. Within a module (but outside of a function), a variable declared as static can be accessed by functions used in the module, but not by functions outside the module. It is a local global variable (it can only be used by the current file).
  3. Within a module, a function declared static can only be called by other functions within the module. That is, the function is limited to the local scope of the module in which it is declared (only available to the current file).

In C, why are static variables initialized only once?

All objects (not just static objects) are initialized only once. Since static variables have a “memory” function, they are never destroyed after being initialized and are stored in the memory area, so they are not initialized again. A variable stored in a static area has a long life. It “lives and dies” with the entire program, so it needs to be initialized only once. The auto variable, because it is stored on the stack, is destroyed as soon as the function call ends.

What does extern “C” do?

The main purpose of extern “C” is to enable C++ code to correctly call other C language code. Extern “C” instructs the compiler to compile this part of the code as C, not C++.

What does const do?

  1. Define variables (local or global) as constants, for example:
const int N=100; // define a constant N=50; // Error, const int n cannot be changed; Error: Constants must be initialized when they are defined
  1. Modifies a function’s argument to indicate that the value of the argument cannot be changed within the function body.
  2. Modify the return value of the function.

    A. If the const return value is a pointer, the contents of the return value cannot be modified, and the return value can only be assigned to the const pointer. Such as:

    Const char * STR = getString () // Define a function char * STR = getString () // Error, because STR is not modified by const char * STR = getString () // Correct

B. If a normal return value, such as an int, is const, it makes no sense to make the return value const since the return value is a temporary variable whose lifetime is over at the end of the function call.

  1. Save space and avoid unnecessary memory allocation. Such as:

    Double I = PI // double I = PI // double I = PI // double I = PI // Double j= PI// no memory is allocated double j= PI// no memory is allocated

When is the const keyword used?

  1. Pertains to general constants. Generic constants are constants of simple type. When such constants are defined, the modifier const can be used either before or after the type specifier. Such as:
Int const x = 2; const int x=2
  1. Modify the constant group. A group of constants can be defined or described in the following format:
,2,3,4,5,6,7,8 int const a [8] = {1} const int a [8] =,2,3,4,5,6,7,8 {1}
  1. Modify regular objects. A constant object is an object constant and is defined in the following format:
Class A: const A: const A:

When a permanent object is defined, it is also initialized, and the object cannot be updated. The modifier const can be placed either after or before the class name.

  1. Modified constant pointer
Const int * p; // A pointer to a constant. Int const*p; int const*p; // int*const p; // A pointer to a constant is essentially a constant and is modified with a pointer. Const int* const p; const int* const p; const int* const p; // A pointer to a constant. That is, the memory that p refers to and the value is immutable
  1. Modify common references. A reference variable that is const is a constant reference. Once initialized, it cannot point to any other object.
  2. Modifies a constant argument to a function. The const modifier can also modify the passing parameters of a function in the following format:
Void Fun (const int Var)

Tells the compiler that Var cannot be changed in the body of the function, thereby preventing unintended or erroneous modifications by the user.

  1. Modify the return value of the function. The const modifier can also modify the return value of a function, indicating that the return value cannot be changed, in the following format:
Const int FunI (); Const MyClass Fun2 ();
  1. Referencing a const in another connection file. The modes of use include
Extern const int 1: extern const int j=10;

What is the difference between new/delete and malloc/free?

  1. New and delete are the C++ operators, while malloc and free are the library functions.
  2. For non-internal data objects, using malloc alone cannot fulfill the dynamic object requirement. In general, the constructor is called when the object is created, and the destructor is automatically called when the object dies. While malloc free is a library function, not an operator, it is outside the compiler’s control and cannot automatically call constructors and destructors. When NEW requests memory for an object, it automatically calls the constructor and initializes the object. Similarly, delete can automatically call the destructor. Mallloc just does one thing, it allocates memory to a variable, and free just frees memory for a variable.
  3. New returns a pointer to the specified type and automatically calculates the size of the requested memory. Malloc requires us to calculate the size of the requested memory and force a pointer to the actual type on return.

Strlen (\ “0”) =? sizeof(“\0”)=?

Strlen (“\0”)= 0, sizeof(“\0”)=2.

Strlen is used to calculate the length of a string (in C/C++, strings end with “\0”). It scans from somewhere in memory (at the beginning of the string, somewhere in the middle, or even some indeterminate memory region) until it hits the first string end \0. It then returns a counter value. Sizeof is a C keyword that gives the sizeof its operand in bytes. The sizeof its operand can be either an expression or a type name enclosed in parentheses.

What’s the difference between sizeof and strlen?

Strlen differs from sizeof in five ways.

  1. Sizeof is the operator (confused? In fact, sizeof is both a keyword and an operator, but not a function), while strlen is a function. Sizeof must be parenthesized if it is a type, and can be left unparenthesized if it is a variable name.
  2. The sizeof operator’s result type is size_t, and its typedef in the header file is of type unsigned int. This type is guaranteed to hold the byte size of the largest object that the implementation establishes
  3. Sizeof can take a type as an argument, strlen can only take a char* and must end in “0”. Sizeof can also take a function as an argument, such as int g (). The value of sizeof (g ()) is equal to the value of sizeof (int, which on 32-bit computers is 4.
  4. The sizeof most compilers is calculated at compile time, so the array dimension can be defined by sizeof (x). Strlen, on the other hand, is computed at runtime to calculate the actual length of the string, not the size of the type in memory. For example, char STR [20] = “0123456789 “, the character array STR is a compile-time fixed array, which on 32-bit machines is sizeof (char) *20=20, and its strlen size is determined at run time, so it is the actual string length of 10.
  5. When an array is passed as an argument to a function, the pointer is passed instead of the array, i.e. the first address of the array is passed.

How to find the number of bytes occupied by int without sizeof?

#include <stdio.h>
#define MySizeof(Value)  (char *)(&value+1)-(char*)&value
int main()
{
    int i ;
    double f;
    double *q;
    printf("%d\r\n",MySizeof(i));
    printf("%d\r\n",MySizeof(f));
    printf("%d\r\n",MySizeof(a));
    printf("%d\r\n",MySizeof(q));
    return 0;
}

The output is:

32 4 April 8

In our example, (char*) & Value returns the first byte of the address of Value, and (char*) (& Value+1) returns the first byte of the address of Value, so the difference between them is the number of bytes it takes up.

What is the difference between struct and union in C?

Struct and union are two different data structures in C language. Both of them are common compound structures, and their differences are mainly reflected in the following two aspects.

  1. Although structure with complex is composed of members of a number of different data types, but the difference is that all members in the association to share a piece of address space, i.e. a consortium members only for a selected, and the structure of all members to take up the space is accumulative, all of its members, members will be stored in a different address. When calculating the total length of a structural variable, the size of its memory space is equal to the sum of the lengths of all its members (byte alignment is required). In a union, all members cannot occupy memory space at the same time; they cannot coexist, so the length of a union variable is equal to the length of its longest member.
  2. Assignments to different members of a union will override other members of the union, and the original values will no longer exist. Assignments to different members of the structure do not affect each other.

Let me give you an example. What is the result of the following code execution?

typedef union {double i; int k[5]; char c; }DATE; typedef struct data( int cat; DATE cow; Double dog;) too; DATE max; printf ("%d", sizeof(too)+sizeof(max));

If we have a 32-bit machine, we have an int (4 bytes), a double (8 bytes), a char (1 byte), and a DATE (1 byte). If we have a DATE, we have an int (20 bytes). Since the double in the union occupies 8 bytes, the union should be aligned with 8 bytes, occupying a multiple of 8 memory space. Data is a structure variable, each variable takes up space separately, and the order is sizeof (int) + sizeof (DATE) + sizeof (double) =4+24+8=36, and the space is 40. So 40 plus 24 is 64.

What are lvalues and rvalues?

An lvalue is a variable or expression that can appear on the left side of an equal sign. Its most important characteristic is that it is writable (addressable). That is, its value can be modified, and if a variable or expression cannot be modified, it cannot be used as an lvalue.

An rvalue is a variable or expression that can only appear on the right side of an equal sign. Its most important feature is its readability. The usual usage scenario is to assign an rvalue to an lvalue.

In general, an lvalue can be an rvalue, but an rvalue does not have to be an lvalue.

What is short circuit evaluation?

#include <stdio.h>
int main()
{
   int i = 6;
   int j = 1;
   if(i>0||(j++)>0);
   printf("%D\r\n",j);
   return 0;
}

The output is 1.

Why is the output one instead of two? In fact, here involves a short-circuit calculation problem. Since I statement is a conditional judgment statement, which is a compound statement combining two simple statements with OR operation, since in OR operation, as long as the values of two expressions participating in OR operation are both true, then the whole operation result is true, and since the value of the variable I is 6, which is already greater than 0, and the statement is already true, No subsequent j+ operations need to be performed to determine true or false, so no subsequent j++ operations need to be performed, and the value of j is still 1.

For an && operation, if one of the two expressions returns false, then the whole expression will return false. If the first statement returns false, then the whole condition will return false regardless of whether the second statement returns true or false. If a>b returns false, the program does not execute the expression n=c>d, so the value of n remains the initial value of 2.

What’s the difference between ++a and a++? How do they work?

The specific operation procedure of a++ is

int temp = a;
a=a+1;
return temp;

The specific operation of plus plus a is

a=a+1;
return a;

The postincrement operator copies the value of the original variable into a temporary storage space and does not return the value of the temporary variable until the operation is complete. So the pre increment operator is more efficient than the post increment operator

memory

How many ways can memory be allocated in C?

  1. Static storage allocation

Memory allocations, such as global variables, static variables, and so on, are completed before the program is compiled and exist throughout the program’s run time.

  1. On the stack

Storage locations for local variables within a function are created on the stack during function execution and are automatically freed at the end of the function execution.

  1. The heap allocation

What’s the difference between a heap and a stack?

  1. Application way

    Space on the stack is allocated/freed automatically by the operating system, and space on the heap is allocated/freed manually.

  2. The application size is limited by stack space. Under Windows, a stack is a data structure extending to a lower address, a contiguous area of memory. The maximum size of the stack is set by the system in advance. In Windows, the size of the stack is 2M. If the requested space exceeds the space available on the stack, the overflow prompt will be provided. Therefore, the space available from the stack is small

    A heap is a large free storage area. A heap is a data structure that scales to high addresses and is a discontinuous area of memory. This is because the system uses the linked list to store the free memory address, which is naturally discontinuous, and the direction of the linked list traversal is from the low address to the high address. The size of the heap is limited by the virtual memory available in the computer system. As you can see, the amount of space the heap can acquire is flexible and large.

  3. The application efficiency stack is automatically allocated by the system, which is faster. But the programmer can’t control it.

    Heap is memory allocated by new. It is usually slow and prone to fragmentation, but it is the easiest to use.

What is the role of the stack in C?

  1. In C, the stack is used to store temporary variables. Temporary variables include function parameters and temporary variables defined within the function. Function call and function call related return address, temporary variables, registers and other functions are saved in the stack, after the return of function transfer from the stack to restore registers, temporary variables and other function running scenarios.
  2. The foundation of multithreaded programming is the stack, and the stack is the cornerstone of multithreaded programming. Each thread has at least one of its own stack, which is used to store the temporary variables of each function when the thread is running and to maintain the function call relationship and function run scene when the function is called and returned. The most basic function of the operating system is to support multithreaded programming, support interrupt and exception handling, each thread has its own stack, interrupt and exception handling also has its own stack, stack is the cornerstone of multithreaded management of the operating system.

What is the stack order of C function parameters?

From right to left.

The advantage of C is that you can change the number of arguments dynamically. In left-to-right push, the first parameter is pushed to the bottom of the stack. Unless you know the number of arguments, you can’t get the leftmost argument from the relative shift of the stack pointer. So what happens is that the number of parameters on the left is uncertain, which is the opposite direction of the number of dynamic parameters. For this reason, function arguments in C are pushed from right to left, mainly to support the variable length argument form.

How does C++ handle return values?

C++ function returns can be returned by value, by constant reference, and occasionally by address. Do not return using addresses in most cases.

Can C++ copy the parameter of the assignment function pass the value?

Can’t. If this is the case, the copy constructor is called by passing the argument to the parameter, which in turn calls the copy constructor (aa = ex. Aa; // The copy constructor is called here. In this loop, the copy cannot be completed and the stack will be full.

Class Example {public: int (a) :aa(a) {// copy constructor (int (a)) {// copy constructor (int (a)); } private: int aa; private: int aa; }; int main() { Example e1(10); Example e2 = e1; return 0; }

How does C++ manage memory?

In C++, virtual memory is divided into code segment, data segment, BSS segment, heap area, file mapping area and stack area.

Code segment: Includes read-only storage, where string constants are stored, and text section, where the machine code of the program is stored.

Data segment: Stores the initialized global and static variables in the program

BSS segment: Stores uninitialized global and static variables (local + global), and all global and static variables initialized to 0.

Heap: When new/malloc is called, memory is allocated dynamically in the heap, and delete/free is required to manually free the requested memory.

Map area: Stores the dynamic link library and file mapping by calling the mmap function

Stack: Use the stack space to store the return address, parameters, local variables, and return values of a function

What is a memory leak?

Say simply namely applied for a piece of memory space, did not release after using.

The way it usually behaves is that the longer the program runs, the more memory it consumes, and eventually it runs out of memory, and the whole system crashes. A block of memory claimed by a program without any Pointers to it is compromised.

How do I detect a memory leak?

  1. Good coding habits, as far as possible in the program segment involving memory, memory leak detection. When the program is stable, it will increase the difficulty and complexity when it comes to detecting memory leaks. Use a function that allocates memory. Once you’re done using it, remember to use the corresponding function to free it.
  2. The pointer of allocated memory is managed by itself in the form of a linked list. After using it, it is deleted from the linked list. The list can be checked at the end of the program.
  3. Smart Pointer in Boost.
  4. Some common tool plug-ins, such as ccmalloc, Dmalloc, Leaky, and so on.

Pointer to the

What’s the difference between an array pointer and a pointer array?

An array pointer is a pointer to an array. It represents a pointer. This pointer points to an array, and the point is the pointer. For example, int (*pa) [8] declares a pointer to an array of eight int elements. An example of an array pointer is shown below.

# include < stdio, h > # include < stdlib. H > void main () {int b [12] =,2,3,4,5,6,7,8,9,10,11,12 {1}; int (*p)[4]; p = b; Printf ("%d\n", **(++p); }

The output of the program is 5.

P is initialized to point to the first address of b. ++p moves the first address of p back four ints. * (++p); Is the address of the first element in the array (p is a pointer to a two-dimensional array, {1,2,3,4}, {5,6,7,8}, {9,10,11,12}). *p refers to {1,2,3,4}, *p refers to the element, {1,2,3,4}, **p refers to 1), the statement ** (++p) will print the first element of the array, 5.

A pointer array represents an array in which the elements are Pointers. Here is another example of a pointer array

#include <stdio.h> int main() { int i; int *p[4]; Int a [4] = {1, 2, 3, 4}; p[0] = &a[0]; p[1] = &a[1]; p[2] = &a[2]; p[3] = &a[3]; for(i=0; i<4; I++) printf (" % d ", * p [I]); printf("\n"); return 0; }

The output of the program is 1234.

What’s the difference between a function pointer and a pointer function?

  1. A function pointer

If a function is defined in a program, at compile time the system allocates a segment of storage space for the function code. The beginning of this segment of storage space is called the address of the function. And the name of the function represents that address. Since it’s an address, we can define a pointer variable to store it, and that pointer variable is called a function pointer variable, or a function pointer for short.

int(*p)(int, int);

This statement defines a pointer to the function variable p. First, it is a pointer variable, so it has a “*”, which is (*p); The first int indicates that the pointer variable can point to a function with a return value of type int. The two ints in parentheses indicate that the pointer variable can refer to a function that takes two arguments and is of type int. We define a pointer to a function that returns a value of type int and takes two integer arguments. We define a pointer to a function that returns a value of type int and takes two integer arguments. P is of type int(*)(int, int).

We see that the definition of a function pointer is to change the “function name” in the “function declaration” to “(pointer variable name)”. Note, however, that the parentheses at the end of “(pointer variable name)” cannot be omitted. The parentheses change the precedence of the operator. If you omit the parentheses, you are not defining a pointer to a function but a function declaration. That is, you are declaring a function whose return value is of type pointer.

Finally, note that pointer variables to functions do not have ++ and — operations.

# include <stdio.h> int Max(int, int); Int main(void) {int(*p)(int, int); Int a, b, c; p = Max; Printf (" Please enter a and b:"); printf(" Please enter a and b:"); scanf("%d%d", &a, &b); c = (*p)(a, b); / / call Max function through a function pointer printf (" a = % d \ nb = % d \ \ n nmax = % d ", a, b, c); return 0; } int Max(int x, int y);} int Max(int x, int y); if (x > y) { z = x; } else { z = y; } return z; }
  1. Pointer to the function

First, it is a function, except that the return value of this function is an address value. The return value of a function must be accepted as a pointer variable of the same type. That is, a pointer function must have a “function return value.” Also, in a calling function, the return value must be assigned to a pointer variable of the same type.

Type name * function name (function argument list);

Where, the postfix operator bracket “()” indicates that this function is a pointer function, and the prefix operator asterisk “*” indicates that this function is a pointer function and its value is a pointer, that is, the type of the value it returns is a pointer. When this function is called, it will get a “point to the return value is…” The “type name” indicates the type to which the function returns a pointer.

The parentheses in “(function argument list)” are function call operators. In a call statement, a pair of parentheses in the argument list of a function cannot be omitted even if the function takes no arguments. An example is as follows:

int *pfun(int, int);

Since “*” has a lower precedence than “()”, pfun is first combined with the “()”, which means that pfun is a function. That is:

int *(pfun(int, int));

This is then combined with the “*” to indicate that the return value of the function is a pointer. Since there is an int in front of it, that means pfun is a function that returns an integer pointer.

#include <stdio.h> float *find(float(*pionter)[4],int n); / / function declarations int main (void) {static float score [] [4] = {{60,70,80,90}, {56,89,34,45}, {34,23,56,45}}; float *p; int i,m; printf("Enter the number to be found:"); scanf("%d",&m); printf("the score of NO.%d are:\n",m); p=find(score,m-1); for(i=0; i<4; I++) printf (" \ t % 5.2 f ", * (p + I)); return 0; } float *find(float(*pionter)[4],int n)/* pt=*(pionter+n); return(pt); }

The function find() is defined as a pointer function whose parameter pointer is a pointer to a one-dimensional array containing four elements. Pointer +n points to row n+1 of score. *(pointer+1) points to the 0th element in the first row. Pt is a pointer variable that points to a floating point variable. Main () calls find() to pass the first address of the score array to Pointer.

What is the difference between an array name and a pointer?

  1. Data storage

The pointer holds the address (the target data address, its own address allocated by the compiler), the memory access offset is 4 bytes, and whatever data is stored in it is parsed by the address type.

Array holds data. The name of the array is the address of the first element. The memory offset is the memory offset to hold the data type. The array name represents the entire array only if the array name is addressed (& array name). The memory offset is the sizeof the entire array (sizeof).

  1. Data access aspect

Pointers access data indirectly, using the dereference symbol (* array name).

An array accesses data directly, either by subscript or by the array name plus the element offset

  1. Using the environment

Pointers are mostly used for dynamic data structures (such as linked lists, etc.) and dynamic memory exploration.

Arrays are mostly used to store a fixed number of uniformly type data structures (such as linear tables, etc.) and implicit allocation.

What is the result of casting a pointer and adding it to the address?

Suppose on a 32-bit machine, with alignment of 4,sizeof(long) is 4 bytes,sizeof(char*) is 4 bytes,sizeof(short int) is 2 bytes, and sizeof(short int) is 2 bytes. The result of sizeof(char) is 1 byte, and sizeof(int) is 4 bytes. Since there is 4-byte alignment on a 32-bit machine, take the following structure as an example:

struct BBB 

{

  long num;

  char *name;

  short int data;

  char ha;

  short ba[5];

}*p;

When p = 0 x100000; The p + 0 x 200 =? (ulong)p+0x200=? (char*)p+0x200=?

In fact, on a 32-bit machine, sizeof (struct BBB) = sizeof (* p) = 4 + 4 + 2 + 2 + 1 + 3 up / * * / + 2 / + 2 * 5 up * * / = 24 bytes, P +0x200=0x1000000+0x200*24; P +0x200=0x1000000+0x200*24; P + sizeof(p)*0x200;

(ulong)p+0x200=0x10000010+0x200 is no longer a pointer addition, but a numerical addition.

(char*)p+0x200=0x1000000+0×200*sizeof(char) The result type is char*.

What’s the difference between a constant pointer, a pointer to a constant, and a constant pointer to a constant?

  1. Pointer to a constant
int * const p

Const p is a pointer to a constant type. The pointer cannot be changed, but the value stored at the address to which the pointer points can be changed.

  1. A pointer to a constant
const int *p

We can’t change the value of a pointer to a constant. We can’t change the value of a pointer to a constant

  1. A constant pointer to a constant
const int *const p

For a “constant pointer to a constant”, you must satisfy both 1 and 2 above, and you cannot change either the value of the pointer or the value to which the pointer points.

What are the similarities and differences between Pointers and references? How to convert to each other?

The same

  1. Is the concept of address, pointer to a memory, its content is the address of the memory; A reference is an alias for a block of memory.
  2. From the memory allocation point of view: both account for memory, the program will allocate memory for the pointer, generally 4 bytes; The essence of a reference is a pointer constant. A point to an object cannot change, but the value of a point to an object can change. Both are address concepts, so they use memory by themselves.

The difference between

  1. Pointers are entities and references are aliases.
  2. The increment (++) operators for Pointers and references have different meanings. Pointers increment memory addresses and references increment values.
  3. References need not be dereferenced (*). Pointers need to be dereferenced. (Check out this blog post on dereferencing, Portal).
  4. References can only be initialized once at the time of definition and cannot be changed thereafter. Pointers are mutable.
  5. References cannot be null, and Pointers can be.
  6. A sizeof reference is the sizeof the object to which it refers. A sizeof pointer is the sizeof the pointer itself. On 32-bit systems, pointer variables typically take up 4 bytes of memory.
#include "stdio.h"

int main(){
    int x = 5;
    int *p = &x;
    int &q = x;
    
    printf("%d %d\n",*p,sizeof(p)); 
    printf("%d %d\n",q,sizeof(q));
} 
// So we get 5, 8, 5, 4

From the results, we can see that references do not need to be dereferenced (*), Pointers need to be dereferenced; I’m using a 64-bit operating system, and the “sizeof pointer” is the sizeof the pointer itself, plus 8 bytes. “Sizeof” returns the sizeof the object itself and the sizeof the int, 4 bytes.

conversion

  1. Pointer referencing: Pointers can be converted to objects by using *, which can be used in reference parameters.
  2. Reference-to-pointer: An object of reference type is addressed with &to get a pointer.
int a = 5; int *p = &a; Void fun(int &x){}// The call to fun uses: fun(*p); //p is a pointer that is converted to the object to which the pointer points. Fun takes a parameter that is a reference.

What is a wild pointer?

  1. A wild pointer is a pointer to unusable memory. When the pointer is created, the pointer cannot automatically point to NULL. In this case, the default value is random.
  2. When a pointer is freed by free or delete, if the pointer is not set to NULL, a wild pointer is generated, because the memory to which the pointer points is only freed, not the pointer itself.
  3. The third cause of wild Pointers is that pointer manipulation goes beyond the scope of a variable.

How to avoid wild Pointers?

  1. Initialize the pointer.
// Initialize the pointer to NULL. char * p = NULL; Char * p = (char *)malloc(sizeof(char)); Char num[30] = {0}; char num[30] = {0}; char num[30] = {0}; char *p = num;
  1. After the pointer is used up, the memory is freed and the pointer is NULL.
delete(p);
p = NULL;

Note: After the malloc function allocates memory:

A. Check whether the allocation is successful (if successful, return the first address of memory; The assignment was unsuccessful, return NULL. You can tell by the if statement.)

B. Clear data from memory (there may be garbage values in malloc allocated space, use memset or bzero function to clear memory)

//s is the starting address of the space that needs to be nulled; N is the number of data bytes to zero. Void bzero (void *s, int n); // If the first address of the empty space is p, value is the value, size is the number of bytes. void memset(void *start, int value, int size);

What is a smart pointer in C++?

A smart pointer is a class that stores Pointers (Pointers to dynamically allocated objects).

In C++ programming, the use of heap memory is a very frequent operation. The application and release of heap memory are managed by the programmer himself. The programmer can improve the efficiency of the program by managing the heap memory by himself, but it is troublesome to manage the heap memory as a whole. In C++11, the concept of smart pointer is introduced to facilitate heap memory management. Using ordinary pointer, easy to cause heap memory leak (forget to release), secondary release, program abnormal memory leak and other problems, the use of smart pointer can better manage the heap memory.

How to solve the memory leak of smart pointer?

Cyclic references in order to solve the cause of a memory leak, the introduction of the weak pointer weak_ptr, weak_ptr constructor does not modify the value of the reference count and not to manage the object’s memory, its similar to an ordinary pointer, but does not point to the reference count of Shared memory, but can detect whether the object of management have been released, So as to avoid illegal access.

pretreatment

What is the purpose of the preprocessor flag #error?

The \#error preprocessor directive is used to generate a compilation error message and stop compilation whenever #error is encountered. The syntax format is #error error-message.

Here’s an example: Programs often have a lot of preprocessing instructions

#ifdef XXX
...
#else
#endif

When the program is large, some macro definitions are specified externally (such as in a Makefile) or in a system header file. If you are not sure if you are currently defining ‘XXX’, you can compile it as follows:

#ifdef XXX
...
#error "XXX has been defined"
#else
#endif

This way, if an error occurs at compile time and the output is XXX Has Been Defined, that means the macro XXX has been defined.

Who is better at defining constants? # define or const?

Both define and const can define constants. The effect is the same, but each has its own emphasis.

Define can replace both constant values, expressions, and even code segments, but it is error-prone, and the introduction of const can enhance the readability of the program, which makes maintenance and debugging of the program easier. Specifically, their differences are mainly manifested in the following three aspects.

  1. DEFINE is used as a simple text replacement. The DEFINE constant’s life cycle ends at compile time and does not allocate memory. It exists in the code segment of the program. A const exists in a segment of the program and is allocated space on the stack. It can be called and passed
  2. A const constant has a data type, while a define constant has no data type. The compiler can do type-safety checks on const constants, such as type, statement structure, etc., but not on define.
  3. Many IDEs support debugging const constants, rather than define constants. Because const modified variables eliminate insecurity between programs, protect constants from modification, and check data types, they greatly improve program robustness. So we tend to use const to define a constant type.

What’s the difference between a typedef and a define?

Typedef and define both alias an object to enhance the readability of a program, but they differ in use and function in the following four ways.

  1. The principle of different

    #define is a syntax defined in C language, which is a preprocessing instruction. During preprocessing, simple and mechanical string substitution is carried out, and no correctness check is done. No matter whether the meaning is correct or not, it is still substituted.

    For example, with # define Pl3.1415926, PI is replaced with 3.1415926 when the program executes area=Pr*r statement. Area =3.1415926*r*r If the number 9 in the # define statement is written as g, the preprocessing is also applied without checking whether it is legitimate or not.

    A typedef is a keyword that is processed at compile time, so a typedef has type checking capabilities. It aliases an existing type in its scope, but cannot use the typedef identifier in a function definition. For example, typedef int INTEGER, which can be used instead of int as the type of an INTEGER variable, such as INTEGER a,b;

Using typedefs to define arrays, Pointers, structures, and other types brings great convenience. It not only makes the program easier to write, but also makes the meaning more clear, thus enhancing the readability. For example: typedef int a[10];

Indicates that a is an integer array of type 10. A can then be used to specify variables, such as statement A, S1, S2; Equivalent to int s1[10],s2[10]. Similarly, typedef void (*p) (void) indicates that p is a pointer to void type.

  1. Function of different

    Typedefs are used to define aliases for types that include not only internal types (int, char, and so on), but also custom types (struct, for example) that make the type easier to remember.

For example: typedef int (*PF)(const char*, const char*)

Define the data type PF for a pointer to a function that returns an int and takes a const char*. Another important use of typedefs is to define machine-independent types. For example, we can define a floating-point type called REAL that has the highest accuracy on the target machine: typedef long double REAL. On a machine that does not support long double, the typedef would look like this: Typedef double real, on a machine that neither double supports, the typedef will look like this: typedef float real.

Define not only aliases types, but also defines constants, variables, compile switches, and so on.

  1. Different scopes

A typedef has its own scope. For example, a typedef has its own scope. For example, a typedef has its own scope.

The program example is as follows:

Void fun() {#define A int} void gun() {// If you use A typedef, you can use // if you use A typedef.
  1. You do things differently with Pointers

The two have different functions when modifying pointer types.

#define INTPTR1 int* typedef int* INTPTR2; INTPTR1 pl, p2; INTPTR2 p3, p4.

INTPTR1 PL, P2 and INTPTR2 P3, P4 had distinct effects. INTPTR1 pl, p2, int*p1,p2, int*p1,p, int*p1,p, int*p1,p, int*p1,p, int*p1 And INTPTR2, p3, p4, because INTPTR2 is meaningful and tells us that it is a pointer to integer data, then p3 and p4 are pointer variables, this sentence is equivalent to int*pl, *p2. As you can see from this, macro substitution is a substitution without any meaning, just a string substitution; A typedef alias for a data type has a meaning.

An example program is as follows

#define INTPTR1  int*
typedef int* INTPTR2  
int a=1;
int b=2;
int c=3;
const INTPTR1  p1=&a; 
const INTPTR2 p2=&b;
 INTPTR2 const p3=&c;

In the code above, const INTPTR1 p1 means that p1 is a constant pointer. You can’t change what p1 points to, but P1 can point to something else. P2 is a pointer constant. You cannot make p2 point to anything else, but you can use p2 to change what it currently points to. INTPTR2 const p3 also declares a pointer constant.

How to use define to declare a constant that indicates how many seconds are in a year (ignoring leap year issues)

#define SECOND_PER_YEAR (60*60*24*365)UL

Include < filename.h > # nclude” filename.h”

For include< filename.h >, the compiler first searches for filename.h from the standard library path, making system file calls faster. For # include “filename.h”, the compiler searches for filename.h from the user’s working path first, and then looks for the system path, making the custom file faster.

What are the functions of a header file?

The role of header files is mainly shown in the following two aspects:

  1. Library functions are invoked through header files. For reasons of source code confidentiality, source code is inconvenient (or not allowed) to be released to users, as long as users are provided with header files and binary libraries. The user simply calls the library function according to the interface declaration in the header file, and does not care how the interface is implemented. The compiler extracts the corresponding code from the library.
  2. Header files can enforce type – safety checking. When an interface is implemented or used in a way inconsistent with the declaration in the header file, the compiler will point out the error, greatly reducing the programmer’s burden of debugging and correcting the error.

Is it possible to define static variables in header files, and why?

No, if you define static variables in the header file, it will be a waste of resources and may cause program errors. Because if you define a static variable in every C file that uses the header, you will have a single static variable in each header file as per the compilation procedure, resulting in wasted space or program errors. It is not recommended to define any variables in the header file, including static variables of course.

Write a “standard” macro MIN that takes two arguments and returns the smaller one. Right?

#define MIN(A,B) ((A) <= (B)? (A) : (B))

How do I print integers from 1 to 1000 without using flow control statements?

Macros define multiple levels of nesting (10, 10, 10) and printf is printed multiple times.

#include <stdio. h> #define B P,P,P,P,P,P,P,P,P,P #define P L,L,L,L,L,L,L,L,L,L #define L I,I,I,I,I,I,I,I,I,I,N #define I printf ("%3d", I ++) #define N printf (" N ") int main() {int I = 1; B; return 0; }

Simple writing, also using multi-level nesting

#include< stdio.h > #define A (x) x; x; x; x; x; x; x; x; x; int main () { int n=1; A (A (A (printf (" % d ", n++); return 0; }

variable

What is the difference between a global variable and a static variable?

  1. Global variables are scoped to the program block, while local variables are scoped to the current function.
  2. Memory is stored differently. Global variables (static global variables, static local variables) are allocated in the global data area (static storage space), which is allocated in the stack area.
  3. Lifecycle is different. Global variables are created as the main program is created, and destroyed as the main program is destroyed. Local variables exist inside local functions, or even inside the body of a local loop, but they do not exist when they exit.
  4. It can be used in different ways. By declaring a global variable, all parts of the program can be used. Local variables can only be used locally.

Can global variables be defined in a way that can be more than one. C file contains header files? Why is that?

You can declare a global variable with the same name as static in different C files.

You can declare a global variable with the same name in different C files, as long as only one of the C files has an initial value assigned to the variable, and the connection will not fail.

Can local variables have the same name as global variables?

Yes, local blocks global.

A local variable can have the same name as a global variable. When a variable is referred to within a function, the local variable with the same name is used, not the global variable.

For some compilers, it is possible to define more than one local variable with the same name within the same function. For example, a local variable with the same name can be defined in both loop bodies, and the scope of that local variable is within that loop body.

function

Please write a function to run before main

__attribute__ allows you to set Function attributes, Variable attributes, and Type attributes.

The key words GNU sets for function properties are as follows:

Alias: Sets the function alias. Aligned: Set the alignment of functions. Always_inline /gnu_inline: Whether the function is inline or not. Constructor /destructor: A function executed before and after the main function is executed. Format: Specifies the position of the format input string of the variable function and the position of the output of the corresponding format. NoReturn: Specifies that this function returns no value. Note that there is no return value here, not that the return value is void. It's a function like _exit/exit/abord where the process ends after the function is executed. Weak: Specifies that a function property is weak, rather than global. If the global function name conflicts with the specified name of the function, the global function name is used.

The complete example code is as follows:

#include <stdio.h> void before() __attribute__((constructor)); void after() __attribute__((destructor)); void before() { printf("this is function %s\n",__func__); return; } void after(){ printf("this is function %s\n",__func__); return; } int main(){ printf("this is function %s\n",__func__); return 0; } // this is function before // this is function main // this is function after

Why must destructors be virtual functions?

Setting the destructor of a parent class that might be inherited to a virtual function ensures that when we create a new subclass and then use a pointer to the object of the subclass, we free up the space of the subclass and prevent memory leaks.

Why is the C++ default destructor not virtual?

The default destructor in C++ is not a virtual function because a virtual function requires an extra virtual table and pointer to a virtual table, which takes up extra memory. For classes that are not inherited, destructors that are virtual waste memory. Therefore, the default destructor in C++ is not a virtual function, but is set to a virtual function only if it is needed as a parent class.

What do destructors do in C++?

If the constructor opens a file, the file will be closed when it is no longer needed. Destructors allow classes to do similar cleanup automatically without having to call other member functions.

Destructors are also special class member functions. In a nutshell, the destructor does the opposite of the constructor. It does some cleaning up before the object is deleted, that is, it does some special finishing work.

What’s the difference between a static function and a virtual function?

Static functions are timed at compile time, and virtual functions are dynamically bound at run time. Virtual functions are called with an additional memory overhead because of the virtual function table mechanism.

What’s the difference between overloading and overwriting?

  1. Overlay is the relationship between subclasses and superclasses, a vertical relationship; Overloading relationships between methods of the same class is a horizontal relationship.
  2. Overrides can only be related by one method or by a pair of methods. Overloading is a relationship between multiple methods.
  3. Overlay is determined by object type (object corresponding storage type); The overloading relationship selects the method body based on the argument list and parameter list of the call.

How does a virtual function table implement run-time polymorphism?

Principle:

Virtual function table is a virtual function of a class of address table, each object is created, there will be a pointer to the virtual function table, each class of the virtual function table, according to the order of the function declarations, will function address exists in the virtual function table, when a subclass object rewrite of the parent class virtual function, virtual function table corresponding to the position of the parent will be covered by subclasses of virtual function address.

Function:

When a subclass object member function is called with a pointer to the parent class, the virtual function table indicates which specific function is to be called.

How does C make function calls?

Most program implementations on CPUs use a stack to support function call operations. The stack is used to pass function arguments, store return information, temporarily store register values for recovery, and store local variables.

Each function call has its own stack frame structure. The stack frame structure is specified by two Pointers, the frame pointer (to the beginning) and the stack pointer (to the top of the stack). Most of the data accessed by the function is based on the frame pointer. Here is the structure:

Stack Pointers and frame Pointers generally have special registers, usually using the EBP register as the frame pointer and the ESP register as the stack pointer.

The frame pointer points to the head of the stack frame structure, which holds the address of the previous stack frame’s head, and to the top of the stack.

Say something about SELECT

  1. SELECT function prototype
int select(int maxfdp,fd_set *readfds,fd_set *writefds,fd_set *errorfds,struct timeval *timeout);
  1. The number of file descriptors

There is a maximum limit to the number of file descriptors that a single process can monitor, usually 1024, which can of course be changed; (#define __FD_SETSIZE 1024)

  1. The ready FD is scanned by polling

Select returns an int, which can be thought of as returning one or more file descriptors ready. The application needs to traversal the entire file descriptor array to find out which FD handles have occurred. Since select scans the file descriptors in a polling manner, The higher the number of file descriptors, the worse the performance

  1. Kernel/user space memory copy

Each time select changes the set of handle data structures (FD set) in the kernel, so each call to select requires copying all the handle data structures (FD set) from user space to kernel space, which incurs huge overhead

  1. How to fire a SELECT

Select is triggered horizontally, and the application will notify the process of a file descriptor that is already in place each time it calls select if it has not completed the IO operation.

  1. advantages

A. Select has good portability and can be cross-platform;

B. Select the timeout accuracy of the monitoring time, accurate to microseconds, while poll is milliseconds.

  1. Disadvantages:

A. The maximum number of file descriptors supported by SELECT is 1024, which cannot be changed according to user requirements;

B. Select copies the set of file descriptors from user mode to kernel mode every time it is called, which is expensive;

C. Select returns a set of ready file descriptors, requiring the user to loop through whether all the file descriptors being listened on are in the set. This is less efficient when the number of listening descriptors is large.

How about fork,wait,exec

Copy the parent process to produce the child to use the fork out a copy of the parent, the only copy of the parent page table, two processes all read the same piece of memory, when have a written process using realistic allocates memory copy mechanism, the exec function can load a elf file to replace the parent process, from the parent and child process can run a different program. Fork returns the pid of the child from the parent, and 0 from the child. The parent that called wait will block until the child’s state changes. If exec is successful, the child process starts running from the new program and returns no value. If it fails, -1 is returned.

An array of

What does the following code mean?

*(A [1]+1), *(&A [1][1]), (*(A +1))[1]

A [1] is the address of row 2. A [1]+1 is offset by one unit (to get the address of row 2, column 2).

The second: [] has a high priority, and A1 takes the address and then takes the value.

The third one: A +1 equals &A [1], so (A +1) = A [1], so (A +1) [1]= A1

Can array indices be negative?

Yes, because the subscript simply gives an offset from the current address, as long as the offset can be located to the destination address. Here is an example of a negative subscript:

Array subscript with negative values:

#include <stdio.h> int main() {int I: int a[5]={0,1,2,3,4}; Int *p=&a[4] for (I =-4; I < = 0; I ++) printf("%d %x\n", p[I], &p[I]); Return O.} // return //0 b3ecf480 //1 b3ecf484 //2 b3ecf488 //3 b3ecf48c //4 b3ecf490

As can be seen from the above example, in C language, array subscript is not impossible to be negative, when the array subscript is negative, compile can pass, and can get the correct result, but it means to address from the current address forward.

Bit operation

How do I find the number of 1’s in the binary representation of an integer?

The program code is as follows:

#include <stdio.h>
int func(int x)
{
    int countx = 0;
    while(x)
    {
        countx++;
        x = x&(x-1);
    }
    return countx;
}
int main()
{
    printf("%d\n",func(9999));
    return 0;
}

The output of the program is 8.

In the above example, the function func () converts x to a binary number and counts the number of ones in that binary number. First, take 9 as an example to analyze, the binary representation of 9 is 1001, and the binary representation of 8 is 1000, and the result is 1000 after executing & operation between the two, and then the result is 0 after executing & operation between 1000 and 0111 (the binary bit of 7).

To understand the heart of this algorithm, you need to understand the following two operations:

1) When a number is subtracted by 1, the rightmost bit of the number becomes 0, and all the bits to the right become 1.

2) The function of x& (x-1) is to remove the last digit 1 of the binary number corresponding to x. So, the number of loops until x is equal to 0 is the number of 1’s in x’s binary number.

How do I solve for the number of zeros in binary

int CountZeroBit(int num) { int count = 0; while (num + 1) { count++; num |= (num + 1); } return count; } int main() { int value = 25; int ret = CountZeroBit(value); Printf (" The number of zeros in the binary bit of %d is %d\n",value, ret); system("pause"); return 0; }

Swap the values of the two variables and leave the third variable alone. So if a=3,b=5, then if a=5,b=3;

There are two ways to do it, one using an arithmetic algorithm, the other using ^(XOR).

a = a + b;
b = a - b;
a = a - b; 
a = a^b; // only for int,char.. b = a^b; a = a^b; or a ^= b ^= a;

Given an integer variable of type a, write two pieces of code. The first sets bit 3 of a, and the second clears bit 3 of a. In both operations, the other bits are kept the same.

#define BIT3 (0x1<<3) 
static int a; 
void set_bit3(void) 
{ 
    a |= BIT3; 
} 
void clear_bit3(void) 
{ 
    a &= ~BIT3; 
} 

Containers and algorithms

What’s the difference between a map and a set? How is the separation achieved?

Map and Set are both C++ associative containers, and their underlying implementation is RB-Tree.

Since RB-tree also provides various operation interfaces opened by map and set, almost all operation behaviors of map and set are just transferred to operation behaviors of RB-tree.

The difference between map and set is:

The elements in the map are key-value pairs: keywords act as indexes, and values represent the data associated with the index. A Set, on the other hand, is a simple collection of keywords. Each element in a Set contains only one keyword.

The iterator of set is const. We cannot change the value of an element. Map allows you to change values, but not keys.

The reason is that map and set are sorted according to keywords to ensure their order. If the key is allowed to be modified, it is necessary to delete the key first, then adjust the balance, and then insert the modified key value to adjust the balance. In this way, the structure of map and set will be seriously damaged, resulting in the failure of Iterator. I don’t know if I should point to the position before or after the change. So STL sets the iterator of set to const and does not allow you to change the iterator’s value; Map iterators, on the other hand, do not allow you to change key values. They allow you to change value values.

Map supports subscripting, set does not.

Map can be subscripted with key, and the subscript operator [] uses the key as the subscript to perform search. If the key does not exist, an element with the key and the default value of type mapped_type is inserted into the map. Therefore, the subscript operator [] should be used with caution in map applications. The mapped_type type does not have a default value and should not be used if you only want to determine whether a key value exists without inserting an element. Use find whenever possible, if it can address a need.

What does the STL allocator do?

The STL allocator is used to encapsulate the low-level details of the memory management of the STL container. In C++, the memory is configured and freed as follows:

The new operation has two phases: (1) A call to ::operator new is used to configure memory; (2) Call the object constructor to construct the object content

The delete operation consists of two phases :(1) calling the object’s hash function; (2) Frees memory by dropping employee ::operator delete

STL allocator allocates memory by alloc::allocate() and allocate memory by alloc::deallocate(). Object construction is handled by ::construct(), and object destructing is handled by ::destroy().

At the same time, in order to improve the efficiency of memory management and reduce the problem of memory fragmentation caused by applying small memory, the SGI STL adopts a two-level configurator. When the allocated space size exceeds 128B, the first level will be used. A second level of spatial configurator is used when the allocated space size is less than 128B. The first level of spatial configurator directly uses malloc(), realloc(), free() functions to allocate and release memory space, while the second level of spatial configurator uses memory pool technology to manage memory through free linked list.

How do STL iterators delete elements?

If we use erase(itertor), the iterator for each element in the back of the vector will fail. Each element in the back of erase will move forward one position, but erase will return the next valid iterator.

Erase erase erase erase erase erase erase erase erase erase erase erase erase erase erase erase erase erase erase erase erase erase erase erase

As for the list, it uses a discontinuous allocation of memory and its erase method returns the next valid iterator, so either of the two correct methods can be used.

How is the MAP data stored in the STL?

A red-black tree. Unordered Map The underlying structure of Unordered Map is a hash table

What’s the difference between map and unordered_map in STL?

Unordered_map is a new container in the C++11 standard. At the bottom of the map, it uses a hash table to complete the mapping function. The map determines whether the elements are the same according to operator< comparison, compares the size of the elements, and then selects the appropriate place to insert them into the tree. So, if you traverse the map (in order traversal), the output is ordered. The order is sorted by the size defined by operator<.

Unordered_map calculates the Hash value of the element to determine whether the element is the same or not. So, if we iterate over unordered_map, the result is unordered.

When you use a map, you need to define an operator< for the key. The use of unordered_map requires defining the hash_value function and overloading operator==. For built-in types, such as String, you don’t have to worry about that, you can just use the default. For custom types to be keys, you need to override operator< or hash_value() yourself.

So, it’s better to use unordered_map when you don’t need to order the results. Insertions, deletions and queries are more efficient than map.

What’s the difference between a vector and a list?

  1. The underlying implementation of vector is an array; A list is a bidirectional linked list.
  2. Vector supports random access; List does not.
  3. Vector is sequential memory, list is not.
  4. Insertions and deletions made by a vector on intermediate nodes result in memory copies, but a list does not.
  5. The vector allocates memory at one time and expands twice when it is insufficient. The list does a memory request every time it inserts a new node.
  6. Vector has good random access performance, but poor insertion and deletion performance. List random access performance is poor, insert delete performance is good.

What is the role of iterators in STL? Why do we need iterators when we have Pointers?

1. Iterators

The Iterator pattern, also known as the Cursor pattern, is used to provide a way to access the elements of an aggregated object sequently without exposing the internal representation of the object. Or it might be easier to say that the Iterator pattern is a pattern applied to an aggregated object that allows us to access the elements in an aggregated object in a certain order (the methods provided by the Iterator) without knowing the object’s internal representation.

Due to the above characteristics of the Iterator pattern: coupling with aggregation objects, it is limited to a certain extent to be widely used. Generally, it is only used for the underlying aggregation support classes, such as STL’s container classes such as List, Vector, Stack, and extended Iterators such as ostream_iterator.

2. The difference between iterators and Pointers

Iterators are not Pointers; they are class templates that behave like Pointers. It simply emulates some of the functions of Pointers by overloading pointer operators such as ->, *, ++, –, and so on. An iterator encapsulates a pointer and is an object that “traversal all or part of the elements in the STL (Standard Template Library) container”. In essence, it encapsulates a native pointer. It is a lift of the pointer concept and provides a higher level of behavior than Pointers. It can implement different ++, — and other operations according to different types of data structures.

Iterators return a reference to an object, not its value, so cout can only print the value after the iterator uses *, not itself.

3. The reason for the iterator

The access mode of Iterator class is to abstract the access logic of different collection classes, so that the collection can be iterated through without exposing the internal structure of the collection.

How does Evoll work?

Call order:

int epoll_create(int size);
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
int epoll_wait(int epfd, struct epoll_event *events,int maxevents, int timeout);

First create an epoll object and then operate on it using epoll_ctl to add descriptions that need to be monitored. These descriptions will form a red-black tree in the form of an epoll_event structure. Then block epoll_wait and enter a big loop. The kernel will put its corresponding structure into a linked list and return the list of events that occurred.

What is the difference between resize and reserve in STL?

Change the number of elements in the current container (size()), eg: vectorv; v.resize(len); The size of v is changed to len. If the size of v is less than len, then we add an element to the container. The value of the element is 0 by default. When Valerie plame ush_back (3); After that, it’s three at the end of v, so it’s len, size of the container is len+1;

If reserve(len) is greater than capacity(len), it allocates a block of space that can hold len objects. If reserve(len) is greater than capacity(len), it allocates a block that can hold len objects. Copy Construtor to destroy the previous v.Size () object; Copy Construtor to destroy the previous memory;

Class and data abstraction

Access permissions for class members in C++?

C++ controls access to member variables and functions through public, protected, and private keywords, which are known as member access qualifiers. Inside the class (inside the code that defines the class), members are accessible to each other, regardless of whether they are declared public, protected, or private. There are no restrictions on access rights. Outside of the class (outside of the code that defines the class), members can only be accessed through objects, and only members with public properties can be accessed through objects, not members with private or protected properties

What is the difference between struct and class in C++?

In C++, you can define classes using structs and classes, both of which can be inherited. The difference is that the default inheritance and access rights for structural are public, while the default inheritance and access rights for classes are private. In addition, the Class can define a template class parameter, such as template.

Can reference data members be defined in C++ classes?

Yes, it must be initialized through the member function initializer list.

What is Object Oriented and Generic Programming?

  1. OOP for short is a kind of programming idea. OOP takes an object as the basic unit of a program. An object contains data and functions that manipulate the data.
  2. Procedure-oriented programming treats a computer program as a set of commands, that is, a sequence of functions executed. In order to simplify the program design, process-oriented functions are continued to be divided into sub-functions, that is, large functions are cut into small functions to reduce the complexity of the system.
  3. Generic programming: Make types parameterized for easy coding by programmers. Type parameterization: enables a program (algorithm) to be logically abstracted, passing as a parameter the type of the object (data) being processed.

What is an rvalue reference and how is it different from an lvalue?

The concepts of lvalue and rvalue:

Lvalue: Can take an address to an expression, or a named object/variable. Generally a persistent object that persists after an expression has ended.

Rvalue: You cannot address an expression, or an anonymous object. A temporary object that ceases to exist at the end of an expression.

The difference between an rvalue and an lvalue reference:

  1. Lvalues are addressable, rvalues are not.
  2. An lvalue can be assigned, an rvalue can’t be assigned, and can be used to assign an lvalue.
  3. An rvalue is mutable, and an rvalue is immutable (for base types only, user-defined type rvalue references can be changed by member functions).

A destructor can be virtual; a constructor cannot. Why?

Constructors cannot be declared virtual. Destructors can and sometimes must be declared virtual. Calling virtual functions inside constructors and destructors is not recommended.

The reasons why constructors cannot be declared virtual are:

The main purpose of virtual functions is that they are inherited by derived classes to produce polymorphism. This is why the compiler includes code to construct the base class in the constructor of the derived class. If the constructor of the base class takes arguments, the derived class must give arguments to the base class in its constructor initializer list. The virtual function is meant to turn on dynamic binding, and the program chooses the method to call based on the dynamic type of the object. However, at the time the constructor is run, the dynamic type of the object is incomplete, and there is no way to determine what type it is, so the constructor cannot be dynamically bound. (Dynamic binding is based on the dynamic type of the object, not the function name. Before the constructor is called, the object does not exist. How can it be dynamically bound?)

What class member functions do C++ hollow classes produce by default?

By default, a C++ hollow class produces the following six functions: the default constructor, the copy constructor, the destructor, the assignment operator-overloaded, the addressing operator-overloaded, the const addressing operator-overloaded, and so on.

class Empty { public: Empty(); // The default constructor Empty(const Empty&); // copy constructor ~Empty(); // destructor Empty& operator=(const Empty&); Empty* operator&(); Empty* operator&(); // const Empty* operator&() const; // Addressing operator const};

object-oriented

What is the difference between object orientation and process orientation?

Object-oriented is different from procedure-oriented in the following four aspects:

1) A different starting point

Object-Oriented uses conventional thinking to deal with problems in the objective world, emphasizing that the “action” of solving the problem domain is directly mapped to the interface between objects. However, process-oriented emphasizes the abstraction and modularization of the process, and constructs or deals with the problems of the objective world with the process as the center.

2) Different hierarchical logical relations

Object-Oriented uses computer logic to simulate physical existence in the objective world, takes the collection class of objects as the unit to deal with problems, makes the computer world close to the objective world as much as possible, so as to make the way to deal with problems clearer and more direct. Object-Oriented uses the hierarchy structure of classes to reflect the inheritance and development among classes. The basic unit of process-oriented problem processing is the module that can clearly and accurately express the process, generalize the relationship and function between the modules or modules with the hierarchical structure of the module, and abstract the problems in the objective world into the process that the computer can handle.

3) The data processing mode is different from the control program mode

Object-Oriented encapsulates data and corresponding code as a whole. In principle, other objects cannot modify their data directly, that is, the modification of objects can only be completed by their own member functions. The control program is activated and run through “event-driven”. While process-oriented is directly through the program to process data, after processing can be shown the results of processing, in the control mode is according to the design call or return to the program, can not free navigation, between the modules there is a control and controlled, transfer and call the relationship.

4) Analysis design is different from coding conversion

Object-oriented software is a smooth process through the analysis, design and coding of the software life cycle. From analysis to design to coding, a consistent model is used to represent the realization of a seamless connection. The process-oriented emphasis on the conversion between analysis, design and coding according to the rules runs through the analysis, design and coding of software life cycle, which realizes a kind of stitched connection.

What are the basic characteristics of object orientation?

The object-oriented programming approach has four basic characteristics:

1) Abtraction: This is to ignore aspects of a topic that are not relevant to the current goal in order to pay more attention to aspects that are relevant to the current goal. The abstraction is not intended to understand the whole problem, but rather to select a part of it, leaving out some of the details for now. Abstract includes two aspects, one is process abstraction, the other is data abstraction.

Process abstraction means that any operation with a clearly defined function can be viewed by the consumer as a single entity, even though the operation may actually be performed by a series of lower-level operations. Data abstraction defines the data type and the operations imposed on objects of that type, and restricts the values of objects that can only be modified and observed by using those operations.

2) Inheritance: This is a hierarchical model that joins classes and allows and encourages reuse of classes. It provides a way to express commonalities explicitly. A new class of an object can be derived from an existing class, a process called class inheritance. The new class inherits the properties of the original class. The new class is called the derived class (child class) of the original class, and the original class is called the base class (parent class) of the new class.

A derived class can inherit methods and instance variables from its base class, and a class can modify or add new methods to better suit a particular need. It also shows the relationship between the general and the particular in nature. Inheritance is a good solution to the problem of software reusability.

3) Encapsulation: it is to surround the process and data, and access to the data can only be through the defined interface. Object-oriented computing begins with the basic notion that the real world can be represented as a series of fully autonomous, encapsulated objects that access other objects through a protected interface. Once the properties of an object have been defined, it is necessary to determine the visibility of those properties, which are visible to the outside world and which are used to represent the internal state.

In this phase, the interface of the object is defined. In general, direct access to the actual representation of an object should be prohibited; instead, the object should be accessed through an operation interface, which is called information hiding. Encapsulation ensures the independence of the module and makes it easier to maintain and modify the program. Changes to the application are limited to the internals of the class, so the impact of the application changes can be minimized.

4) Polymorphism: it allows objects of different classes to respond to the same message. The same copy-and-paste operation, for example, works differently in a word processor than it does in a drawing program. Polymorphism includes parameterized polymorphism and inclusion polymorphism. Polymorphism language has the advantages of flexibility, abstraction, behavior sharing and code sharing, which solves the problem of application function namesake well.

What is Deep Copy? What is a shallow copy?

A deep copy is a complete copy. All the members of the two objects are separate copies. Furthermore, the member objects within the member objects are separate copies.

Some member variables in a shallow copy may be shared, and a deep copy, if not thorough, is a shallow copy.

What is a friend?

Some members can only be accessed inside a member function of the class. If you want to access a private member of an object elsewhere, you can only do so indirectly through the interface provided by the class (member functions). This brings the benefit of data hiding for future application expansion, but it also adds to the hassle of writing the application.

C++ evolved from the structured C language, which needs to accommodate the habits of structured design programmers, so it can’t restrict the scope of access to private members too much.

The C++ designers decided that if programmers were really afraid to go to the trouble of directly accessing private members of an object outside of a member function of a class, it would be a compromise between immediate and long-term benefits to accommodate their wishes. Thus, C++ has the concept of friends. To put it another way, this is like saying that friends can be trusted, so you can tell them something about yourself.

Friends provide a mechanism for ordinary functions or class member functions to access private or protected members of another class. That is, there are two forms of friends:

(1) friend function: ordinary function to access a private or protected member of a class.

(2) Friends: member functions in class A access private or protected members in class B.

Can a base class’s constructor/destructor be inherited by a derived class?

The constructor destructor of a base class cannot be inherited by a derived class.

The constructor of a base class cannot be inherited by a derived class, which needs to declare its own constructor. When designing the constructor of a derived class, consider not only the initialization of the data members added by the derived class, but also the initialization of the data members of the base class. When we declare a constructor, we only need to initialize the new members of the class. We need to call the base class constructor to initialize the inherited members of the base class.

The destructor of a base class cannot be inherited by a derived class. A derived class needs to declare its own destructor. The declaration method is the same as the destructor of a normal (non-inherited) class. There is no need to explicitly call the destructor of the base class, and the system automatically calls it implicitly. Note that the destructor is called in the reverse order of the constructor.

What is the difference between initializer list and constructor initializer?

The constructor initializer begins with a colon, followed by a comma-separated list of data members, each of which is followed by an initializer in parentheses. Such as:

Ival (0), dval(0.0) {// Ival (0), dval(0.0) {// Ival (0), dval(0.0) {// Dval (0.0)

The above example looks no different from the constructor below, which uses no initializer:

Example::Example()  
{      
  ival = 0;      
  dval = 0.0; 
} 

Indeed, the result of both constructors is the same. The difference, however, is that the above constructor (the constructor that uses the initializer) displays the members of the initializer class; Constructors that do not use initializers assign values to class members and do not explicitly initialize them.

Initialization and assignment are not much different for members of built-in types, like any of the constructors above. But sometimes we must use a constructor with an initializer:

  1. A member type is a class that has no default constructor. If no display initializer is provided, the compiler implicitly uses the default constructor for the member type. If the class does not have a default constructor, the compiler’s attempt to use the default constructor will fail.
  2. A const member or member of reference type. Because const objects or reference types can only be initialized, we cannot assign them a value.

What are some cases in C++ where you can only use initializers, but not assignments?

The constructor initializer begins with a colon, followed by a comma-separated list of data members, each of which is followed by an initializer in parentheses. Example:Example Ival (o,dva (0.0) {}, where ival and dva are two data members of the class.

In C++ language, the principle of assignment and initializer is different. Assignment is to delete the original value and give a new value. Initializer opens up space and initializer is completed at the same time, giving a value directly

So, in C++, assignment is not used in the same way as initializers. There are three situations in which initializers can be used, but assignment cannot be used:

  1. When a class contains const or reference member variables, they can only be initialized, not assigned. Constants cannot be assigned, they can only be initialized, so they must be initialized in the initializer list. C++ references must also be initialized, so they must be initialized in the initializer list.
  2. When the base class does not have a default constructor, this is done by calling the constructor of the base class in the constructor initializer list of the derived class.
  3. If the member type is a class that does not have a default constructor, you can only use an initializer list. If no explicit initialization is provided, the compiler implicitly uses the default constructor of the member type, and attempts to use the default constructor will fail

What is the order in which the member variables of a class are initialized?

  1. When a member variable is initialized with an initializer list, it is independent of the order in which the member list is initialized in the constructor, only of the order in which the member variable is defined. This is because the order in which member variables are initialized depends on the order in which they are in memory, and the order in memory is determined at compile time based on the order in which variables are defined. This is covered in detail in Effectivecc ++.
  2. If not initialized with an initializer list, when initialized inside the constructor, the position of the member variable in the constructor is dependent.
  3. Note: Class members cannot be initialized when they are defined
  4. Note: const member constants in a class must be initialized in the constructor initializer list.
  5. Note: static member variables in a class must be initialized outside the class.
  6. Static variables are initialized in the order that a static variable of the base class is initialized first, followed by its derived classes. Until all static variables are initialized. It is important to note that global and static variables are initialized out of order. This is understandable because both static and global variables are placed in a common memory area. Static variables can be thought of as global variables with “scope”. After all the initialization is done, the main function is called, and if the constructor of a class is executed, the base class’s member variables are initialized first.

How do I initialize a class when it is a member variable of another class?

The sample program is as follows:

class ABC { public: ABC(int x, int y, int z); private : int a; int b; int c; }; Class MyClass {public: MyClass(): ABC (1,2,3) {} private: ABC; };

In the above example, because ABC has an explicit constructor with arguments, it cannot rely on the compiler to generate a no-argument constructor, so it must use the initializer list: ABC (1,2,3) to construct the ABC object.

Can C++ design and implement a class that cannot be inherited?

The final keyword is defined in Java. Classes decorated with final cannot be inherited. However, there is no final keyword in C++, so it takes some effort to implement this requirement.

The first thing that comes to mind is that in C++, the constructor of a child class automatically calls the constructor of the parent class. Similarly, the destructor of the child class automatically calls the destructor of the parent class. To make a class uninheritable, we simply define its constructor and destructor as private functions. Then when a class tries to inherit from it, it will inevitably result in a compile error by trying to call the constructor, destructor.

The constructor and destructor of this class are both private functions. How can we get an instance of this class? We can create and release instances of the class by defining statics. Based on this idea, we can write the following code:

/// // Define a class which can't be derived from  /// class FinalClass1
{
public :      
static FinalClass1* GetInstance()     
 {          
   return new FinalClass1;    
  }        
static void DeleteInstance( FinalClass1* pInstance)    
  {            
 delete pInstance;         
   pInstance = 0;     
 }  
 private :      
 FinalClass1() {}     
 ~FinalClass1() {}
};

This class cannot be inherited, but it is a little different from the ordinary classes, and a little inconvenient to use. For example, we can only get instances on the heap, not on the stack. Is it possible to implement a class that works the same as a normal class except that it can’t be inherited? There is always a way, but it takes some finesse. See the following code:

 /// // Define a class which can't be derived from  /// template <typename T> class MakeFinal
{     
  friend T;
 private :     
  MakeFinal() {}    
  ~MakeFinal() {}
};   
class FinalClass2 :
 virtual public MakeFinal<FinalClass2>
{
public :      
 FinalClass2() {}  
    ~FinalClass2() {}
};

This class works like a normal class and can be used to create instances on the stack or on the heap. Although the constructor and destructor of the class makeFinal

are private, since the class FinalClass2 is a friend of it, Therefore, calling the constructor and destructor of makeFinal

in FinalClass2 will not cause compilation errors. But when we try to inherit a class from Finalclass2 and create an instance of it, we do not compile it.

class Try : public FinalClass2
{
 public :    
   Try() {}   
   ~Try() {}
};    Try temp; 

Since the class FinalClass2 is inherited from the class makeFinal

virtual, when the Try constructor is called, The constructor for makeFinal

is called directly instead of just skipping FinalClass2. Unfortunately, Try is not a friend of MakeFinal

and therefore cannot call its private constructor.

Based on the above analysis, a class that attempts to inherit from Finalclass2, once instantiated, will result ina compile error and therefore Finalclass2 cannot be inherited. This meets our design requirements.

The constructor does not return a value, so how do you know if the object was successfully constructed?

By “construct” I don’t mean just allocating the memory of the object itself, but the initialization that is done when the object is created (such as opening a file, connecting to a database, etc.).

Because the constructor returns no value, the only way to notify an object of a construction failure is to throw an exception in the constructor. When an exception is thrown in a constructor, the object’s destructor will not be executed. When the object is partially constructed, the constructed children will be destructed in reverse order.

What is the difference between Public, protected, and private inheritance?

Public, protected, and private inheritance are three common types of inheritance.

  1. Public inheritance

For subclass objects, when public inheritance is adopted, the visibility of base class members to subclass objects is the same as that of general class members to objects: public members are visible, but other members are not.

For subclasses, the public and protected members of the base class are visible. When the public and protected members of the base class are members of the derived class, they maintain their original visibility (public members of the base class are still public in the subclass, protected members are still protected in the subclass). Private members of the base class are not visible, private members of the base class are still private, and subclasses are not accessible.

  1. Protect the inheritance

Protected inheritance is characterized by the fact that all public and protected members of a base class are protected members of the derived class and can only be accessed by its derived member functions or friends. Private members of the base class are still private. As you can see, all the members of the base class are invisible to the objects of the subclass.

  1. Private inheritance

Private inheritance is characterized by the fact that both the public and protected members of the base class are private members of the derived class and cannot be accessed by subclasses of that derived class.

Does C++ provide functions with default arguments?

C++ can define default parameter values for functions. Default arguments are automatically used when no argument corresponding to a parameter is specified in a function call.

Syntax and usage of default parameters:

(1) When a function is declared or defined, it is directly assigned to the parameter. This is the default parameter.

(2) In the function call, omit some or all of the parameters. The default parameter can be used instead.

When you normally call a function, you are given an argument for each argument to the function. Such as:

void delay(int loops=1000); Void delay(int loops) {if(loops==0) {return; } for(int i=0; i<loops; i++) ; }

In the example above, if we define loops as the default value of 1000, then whenever we call delay() in the future, we do not assign a value for loops, and the program automatically treats loops as 1000. For example, when the delay(2500) call is executed, the parameter value for loops is explicit and set to 2500. When delay() is executed, loops takes the default value of 1000.

Default arguments are provided in the function declaration, and when both are declared and defined, they are not allowed in the definition. If the function is defined only, then the default parameters may appear in the function definition. Such as:

Oid point (int = 3, int = 4). Void point(int x, int y) void point(int x, int y) {cout<<x<<endl; cout<<y<<endl; }

If a group of overloaded functions (which may take default arguments) all allow the same number of arguments to be called, an ambiguous call will result. Such as:

void func(int); Void func(int, int=4); void func(int, int=4); Void func(int=3, int=4); void func(int=3, int=4); // Overload function 3 with default func(7); // Error: Which of the three overloaded functions is called? Func (20, 30); // Error: Which of the next two overloaded functions is called?

Virtual functions

What is a virtual function?

When a pointer to a base class operates on an object of its polymorphic class, it can call the corresponding function based on the object it points to. This function is called a virtual function.

What a virtual function does: After a virtual function is defined in the base class, the virtual function can be redefined in the derived class, and the base class pointer or reference can be used to dynamically call the base class and the function with the same name in different derived classes during the runtime of the program. (If a virtual is not redefined in a derived class, it inherits the virtual of its base class.)

Here is an example of a virtual function:

#include "stdafx.h" #include<iostream> using namespace std; Class Base {public: virtual void Print()// printf("This is class Base! \n"); }}; Public: void Print() {"This is class Derived1! "; public: void Print(); \n"); }}; Public: void Print() {"This is class Derived2! "} public: void Print(); \n"); }}; int main() { Base Cbase; Derived1 Cderived1; Derived2 Cderived2; Cbase.Print(); Cderived1.Print(); Cderived2.Print(); cout << "---------------" << endl; Base *p1 = &Cbase; Base *p2 = &Cderived1; Base *p3 = &Cderived2; p1->Print(); p2->Print(); p3->Print(); } /* This is Class Base! This is Class Derived1! This is Class Derived2! --------------- This is Class Base! This is Class Derived1! This is Class Derived2! * /

It’s important to note that while virtual functions are very useful, not all functions need to be defined as virtual functions when using virtual functions, because there is a cost to implementing virtual functions. There are a few things to be aware of when using virtual functions:

(1) You only need to declare a function as virtual by using the keyword virtual in the class body of the declared function, but you do not need to use the keyword virtual when defining the function.

(2) When a member function in the base class is declared as a virtual function, the function with the same name in the derived class automatically becomes a virtual function.

(3) A non-class member function cannot be defined as a virtual function. A global function and a static member function and a constructor of a class member function cannot be defined as a virtual function, but a destructor can be defined as a virtual function.

(4) The destructor of the base class should be defined as a virtual function, otherwise it will cause a memory leak. The base destructor does not declare virtual. When the base pointer points to a derived class, the delete pointer does not call the derived destructor. With virtual, the derived destructor is called first and then the base destructor is called.

How does C++ implement polymorphism?

Polymorphism is implemented by virtual functions in C++. The essence of a virtual function is to access a function defined by a derived class through a pointer to the base class. Each class that contains a virtual function has a virtual table pointer inside the example object. The virtual table pointer is initialized to the memory address of the class’s virtual table. Therefore, in the program, no matter how the object type is converted, the internal pointer of the virtual function table of the object is fixed, so as to realize the dynamic call to the object function. This is the principle of C++ polymorphism.

What does a pure virtual function mean?

A pure virtual function is a special kind of virtual function with the following format

Class < class name > {virtual() function return value type virtual function name (parameter list) =0; . }; Class < class name >

Since, in many cases, virtual functions cannot be meaningfully implemented in a base class, the implementation of the function must be left to the derived class. Animals, for example, as a base class can derive the tiger, peacock and other subclasses, but the animals themselves generate objects out of bounds, at this point the function in the animal can be defined as a pure virtual function, if there is a pure virtual function in the base class, then the pure virtual function must be implemented in subclasses, otherwise the subclass will not be able to be instantiated, cannot achieve polymorphism.

Classes that contain pure virtual functions are called abstract classes, which cannot generate objects. Pure virtual functions are never called; they are used to uniformly manage subclass objects.

What function cannot be declared virtual?

Some common functions that cannot be declared virtual are: normal functions (non-member functions); Static member function; Inline member function; Constructor; Friend functions.

1. Why doesn’t C++ support normal functions as virtual functions? Ordinary functions (non-member functions) are overridden and meaningless because they are overloaded, so the compiler binds them at compile time.

2. Why doesn’t C++ support constructors as virtual functions? The reason for this is simple and largely semantic and therefore unsupported. Because constructors are designed to explicitly initialize object members, virtual functions are primarily designed to handle objects correctly without fully understanding the details. In addition, the virtual function is in different types of objects to produce different actions, now the object has not been generated, how to use the virtual function to complete the actions you want to complete. (This is not a classic paradox.)

3. Why doesn’t C++ support inline member functions as virtual functions? In fact, it is very simple, that inline function is to expand directly in the code, reduce the cost of function call, virtual function is to inherit the object can accurately perform their own actions, this is not possible to unify. (Again, inline functions are expanded at compile time, and virtual functions are only dynamically bound at run time.)

4. Why doesn’t C++ support static member functions as virtual functions? It is also simple. Static member functions have only one code per class, which is shared by all objects, and there is no need for dynamic binding.

5. Why doesn’t C++ support friend functions as virtual functions? Because C++ does not support friend function inheritance, there is no virtual function for functions that do not have an inheritance feature.

How do I prevent a class from being instantiated in C++?

You can prevent a class from being instantiated in C++ by using an abstract class, or by declaring the constructor private. An abstract class cannot be instantiated because it does not represent a class of concrete things. It is an abstraction of the common characteristics of many similar concrete things. For example, as a base class, animals can be subclasses such as tigers and peacocks, but it is unreasonable for animals to generate objects themselves.

conclusion

If you see a good information on the Internet, or in the written test interview encountered information not in the knowledge points, you can contact me, I will sort out for you. Please contact the author in time if there is any error or inappropriateness in the materials.

I stayed up late to sort out these contents, and recently I am still revising my big paper. There are a lot of things. Creation is not easy, we do not forget to click the “like” support, it is not in vain to stay up late, worthy of my hair off.

Down again in the end, making links (https://github.com/ZhongYi-Li…