[interview] sorting out common interview questions in C + +

Posted by tron00 on Sat, 01 Jan 2022 04:26:06 +0100

  • What is the difference between the declaration and definition of variables

    The definition of a variable allocates address and storage space for the variable, and the declaration of a variable does not allocate address. A variable can be declared in multiple places,  
    But only in one place. join extern Modified is the declaration of a variable, indicating that the variable will be defined outside the file or in the later part of the file.
    Note: in many cases, a variable only declares that it does not allocate memory space. It is not initialized until it is used to allocate memory space, such as external variables
    
    int main() 
    {
       extern int A;
       //This is A declaration, not A definition. Declaration A is an external variable that has been defined
       //Note: when declaring external variables, you can remove the variable type, such as extern A;
       dosth(); //Execution function
    }
    int A; //Yes, it defines an external variable with A as an integer
    
  • Write the if statement comparing int, bool, float, pointer variable and "zero value"

    //int vs. zero
    if (n==0)
    if (n!=0)
    
    //bool vs. zero
    if (flag)  // Indicates that flag is true 
    if (!flag) // Indicates that the flag is false 
    
    //float vs. zero 
    const float EPSINON = 0.00001;
    if ((x >= - EPSINON) && (x <= EPSINON) //Where EPSINON is the allowable error (i.e. accuracy).
    	
    //Pointer variable and zero value comparison 
    if (p == NULL)
    if (p != NULL)
    
  • Can structures be assigned directly

    When declared, it can be initialized directly, and different objects of the same structure can also be assigned directly
     Be careful when containing pointer "members" in.
    Note: when multiple pointers point to the same section of memory, releasing this section of memory by one pointer may lead to other pointers
     Illegal operation of. Therefore, before releasing, make sure that other pointers no longer use this memory space.
    
  • The difference between sizeof and strlen

    1.sizeof Is an operator, strlen Is a library function.
    2.sizeof The parameter can be a data type or a variable, and strlen Can only end with'\0'String as an argument.
    3.The compiler calculates it at compile time sizeof Results, and strlen Functions must be evaluated at run time. also sizeof It's a number
      According to the size of memory occupied by the type, and strlen The actual length of the string is calculated.
    5.Array do sizeof The parameters of are not degenerate and are passed to strlen It degenerates into a pointer
    
  • Write a "standard" macro MIN

    #define min(a,b)((a)<=(b)? (a) : (b)) / / judge the size of a and B. If a is less than or equal to B, output a; otherwise, output B
    
  • ++The difference between i and i + +

     ++i First increment by 1 and then return, i++Return first i,Increase by 1
    
  • What does volatile do

    1.A class of parallel device hardware registers called status registers.
    2.A non automatic variable that an interrupt service subroutine will access.
    3.A variable shared between multiple threads by several tasks.
    Note: Although volatile It is widely used in embedded system, but in PC In multithreading of software,
    volatile Modified critical variables are also very practical.
    
  • Can a parameter be both const and volatile

    Yes, use it const and volatile At the same time, modify the variable to indicate that the variable is read-only inside the program and is not allowed to be deleted
     What can be changed is only changed when the external conditions of the program change, and the compiler will not optimize this variable. Each use
     When reading this variable, be careful to read the value of this variable in memory instead of reading its backup in the register.
    
    Note: you must pay attention here const What you mean, const It just doesn't allow the code in the program to change a change
     Quantity, which works at compile time. It does not actually prohibit the read and write characteristics of a certain section of memory.
    
  • What's the difference between a and & A

    &a: It means "variable" a The address of the.
    
    *a: Used in different places, the meaning is also different.
    1.In the declaration statement,*a Explain only a Is a pointer variable, such as int *a;
    2.In other statements,*a There is no previous operand and a Is a pointer,*a Representative pointer a Data stored in the address pointed to, such as b=*a;
    3.*a There are operands before and a Is a normal variable, a Represents multiplied by a , as c = ba. 
    
  • What is the difference between global variables and local variables? How? How do operating systems and compilers know?

    1.Global variable is a variable that can be accessed by the whole program. Anyone can access it. The lifetime of the whole program is from running to the end (at the end of the program)
    Memory release);
    2.The local variable exists in the module (subroutine, function), only the module can access it, other modules cannot access it directly, and the module ends
    (After the function is called, the local variables disappear and the occupied memory is released.
    3.The operating system and compiler may be known by the location of memory allocation. Global variables are allocated in the global data segment and run at the beginning of the program
     Loaded when.Local variables are allocated in the stack.
    
  • Briefly describe the memory allocation of C + + program compilation

    1. Allocate from static storage area:
    Memory is allocated when the program is compiled, and it exists throughout the running period of the program. Fast
     It is not easy to make mistakes, because there is a system that will deal with the aftermath. For example, global variables, static Variables, constants, strings, etc.
    2. Allocate on stack:
    When the function is executed, the storage units of local variables in the function are created on the stack. These storage units are created when the function is executed
     The unit is automatically released. The stack memory allocation operation is built into the instruction set of the processor, which is very efficient, but the allocation
     Memory capacity is limited. Size 2 M. 
    3. Allocate from heap:
    Dynamic memory allocation. The program is used when running new The programmer is responsible for when to use any size of memory delete Free memory.
    The lifetime of dynamic memory is determined by the programmer, which is very flexible. If space is allocated on the heap, it is the responsibility to recycle it, otherwise the running program will fail
     In addition, frequent allocation and release of heap space of different sizes will produce in heap fragments.
    
    One C ++When compiling the program, the memory is divided into five storage areas: heap area, stack area, global area, text constant area and program code area.
    
  • Briefly describe the differences between strcpy, sprintf and memcpy

    1.Different operation objects, strcpy Both operands of are strings, sprintf The operation source object can be a variety of data types, and the destination operation
     Object is a string, memcpy The two objects of are two arbitrary operable memory addresses, which are not limited to what data types.
    2.Different execution efficiency, memcpy highest, strcpy Second, sprintf The efficiency is the lowest.
    3.Different functions, strcpy It mainly realizes the copy between string variables, sprintf It mainly realizes the conversion from other data type formats to strings
     Turn, memcpy It is mainly the copy between memory blocks.
    
    be careful: strcpy,sprintf And memcpy Can realize the copy function, but for different objects, select the appropriate function to realize the copy function according to the actual needs.
    
  • Please resolve the meaning of (* (void (*) ()) 0 ()

     void (*0)( ) : Is a return value of void,Function pointer 0 with null argument.
    (void (*)( ))0: Convert 0 to a return value of void,Function pointer with null argument.
    *(void (*)( ))0: Add on the basis of the previous sentence*Indicates that the whole is a return value of void,Function with no parameters and starting address 0
     The name of the number.
    (*(void (*)( ))0)( ): This is the function call corresponding to the function name in the previous sentence.
    
  • What's the difference between typedef and define

	1.Different usage: typedef It is used to define an alias of a data type to enhance the readability of the program. define Mainly used to define constants, and
	Write complex and frequently used macros.
	2.Different execution times: typedef It is part of the compilation process and has the function of type checking. define Is a macro definition, a precompiled part, and its
	Before compilation, it simply replaces the string without type checking.
	3.Different scopes: typedef Scope qualified. define No scope constraints, as long as it is in define The references after the declaration are correct
	of
	4.The operation of the pointer is different: typedef and define There is a big difference when defining pointers.
	
	be careful: typedef The definition is a statement, because a semicolon is added at the end of the sentence. and define It's not a sentence. You can't add a semicolon at the end of the sentence.
  • Difference between pointer constant and constant pointer

    Pointer constant: the value pointed by the pointer can be modified, and the direction pointed by the pointer cannot be changed.
    Constant pointer: the value pointed to by the pointer cannot be modified, and the direction pointed to by the pointer can be changed.
    
  • Briefly describe the similarities and differences between queue and stack

    Both queue and stack are linear storage structures, but their operations of inserting and deleting data are different. Queue is "first in first out" and stack is "last in first out".
    
    Note: distinguish between stack area and heap area. The heap area is accessed in "random order", while the stack area is "last in first out".
    The stack is automatically allocated and released by the compiler to store the parameter values of functions, the values of local variables, etc. Its operation is similar to that of a number
     According to the stack in the structure.
    The heap is usually allocated and released by the programmer. If the programmer does not release it, it may be released by the programmer at the end of the program OS Recycling. 
    The allocation method is similar to a linked list. It is different from the heap and stack in this problem. The stack is just a number
     According to the structure, the heap area and stack area are different memory storage areas of the program.
    
  • Set the value of the integer variable with address 0x67a9 to 0xaa66

    int *ptr; 
    ptr = (int *)0x67a9; 
    *ptr = 0xaa66; 
    
  • How to avoid "wild pointer"

    1.Pointer variable was not initialized when declared. Solution: when the pointer is declared, it can be initialized. It can be a specific address value or let it point to NULL. 
    2.Pointer p cover delete After that, it is not set to NULL. Solution: after the memory space pointed to by the pointer is released, the pointer should point to NULL. 
    3.Pointer operation is beyond the scope of the variable. Solution: release the address space of the variable and let the pointer point to before the scope of the variable ends NULL. 
    
  • Can reference data members be defined in C + + classes

     Yes, it must be initialized through the member function initialization list.
    
  • Access rights of class members in C + +

    C ++adopt public,protected,private Three keywords are used to control the access rights of member variables and member functions,
    They represent public, protected and private respectively, and are called member access qualifiers.
    Inside the class (inside the code that defines the class), regardless of whether the member is declared as public,protected still
    private ,They can access each other without restrictions on access rights. Outside the class (define the code of the class)
    Outside), members can only be accessed through objects, and members can only be accessed through objects public Member of property, no
     Can access private,protected Member of property
    
  • What is an R-value reference and what is the difference between it and an l-value?

    Concepts of left and right values:
    Lvalue: a persistent object that can take an address or a named object and still exists after the expression ends;
    Right value: can't get address, anonymous object, temporary object that no longer exists after the expression ends; difference:
    The left value can be addressed, while the right value cannot;
    The left value can be assigned, but the right value cannot;
    The left value can be changed, but the right value cannot (it is only applicable to basic types, and the right value reference of user-defined types can be changed through member functions);
    
  • Talk about the four cast transformations in c + +

    C ++The four types of conversions in are: static_cast,  dynamic_cast,  const_cast, reinterpret_cast
    1.const _cast
     Used to const Variable to non const
    2.static_cast
     Used for various implicit conversions, such as non const turn const,void*Rotating pointer, etc, static_cast It can be used for polymorphic upward transformation,
    If the downward rotation can succeed but is not safe, the result is unknown;
    3.dynamic_cast
     Used for dynamic type conversion. It can only be used for classes with virtual functions, and can be used for up and down conversion between class hierarchies. only
     Can rotate pointer or reference. When converting down, if it is illegal***For pointer return NULL,For references
     abnormal ***.  To understand the principle of internal conversion.
    Up conversion: refers to the conversion from a subclass to a base class
     Downward conversion: refers to the conversion from a base class to a subclass
     It determines whether the runtime type of the variable and the type to be converted are the same when the statement is executed
     Whether downward conversion is possible.
    4.reinterpret_ cast
     Almost everything can be turned, such as int Turning the pointer may cause problems, so use it as little as possible;
    
  • What are the member functions of empty classes in C + +

    1.Default constructor.
    2.Default copy constructor.
    3.Default destructor.
    4.Default assignment operator.
    5.Default addressing operator.
    6.Default addressing operator const . 
    Note: some books simply introduce the first four functions. The latter two functions are not mentioned. But back here
     The two functions are also the default functions of empty classes. It should also be noted that only when these functions are actually used
     The compiler will define them later.
    
  • Four smart pointers to smart pointer in c + +: shared_ ptr, unique_ ptr, weak_ ptr, auto_ Understanding of PTR

    C ++Four smart pointers inside:  auto_ptr,  shared_ptr,  weak_ptr,  unique_ptr
     The last three are c++11 Support, and the first has been deprecated by 11.
    
    The function of smart pointer is to manage a pointer, because there are the following situations: the requested space is at the end of the function
     Forget to release, causing a memory leak. Using smart pointers can avoid this problem to a great extent, because smart
     A pointer is a class. When it exceeds the scope of the class, the class will automatically call the destructor, and the destructor will automatically
     Free resources. Therefore, the function principle of smart pointer is to automatically release the memory space at the end of the function without hands
     Automatically free up memory space.
    
    1. unique_ptr(replace auto_ptr)
        
        unique_ptr Realize the concept of exclusive ownership or strict ownership to ensure that only one smart pointer can be used at the same time
    	To point to the object. It is important to avoid resource leakage(For example, "with" new After the object was created, it was forgotten because of an exception
    	call delete ")Especially useful.
    
    	//Adopt ownership model.
    	unique_ptr<string> p3 (new string ("auto"));   //#4
    	unique_ptr<string> p4;                       //#5
    	p4 = p3;//An error will be reported!!
    	//The compiler considers p4=p3 illegal, which avoids the problem that p3 no longer points to valid data. Therefore, unique_ptr ratio auto_ptr is safer.
    	
    	//In addition, unique_ptr is also smarter: when a program tries to put a unique_ptr assigned to another
    	//If the source is unique_ptr is a temporary right value, which is allowed by the compiler; If source
    	//unique_ptr will exist for some time, and the compiler will prohibit it, such as:
    	unique_ptr<string> pu1(new string ("hello world"));
    	unique_ptr<string> pu2;
    	pu2 = pu1;                                      // #1 not allowed
    	unique_ptr<string> pu3;
    	pu3 = unique_ptr<string>(new string ("You"));   // #2 allowed
    
        among #1 Leave hanging unique_ptr(pu1),This may cause harm. and#2 will not leave hanging
    	unique_ptr,Because it calls unique_ptr Constructor that creates a temporary object
    	Transfer of ownership to pu3 Will be destroyed. This situational behavior shows that, unique_ptr
    	Better than allowing two assignments auto_ptr  . 
    
    	Note: if you really want to perform something similar to#1. To safely reuse this pointer, you can assign it a new value.
    	C ++There is a standard library function std::move(),So you can put one unique_ptr To another.
    	For example:
    	unique_ptr<string> ps1, ps2;
    	ps1 = demo("hello");
    	ps2 = move(ps1);
    	ps1 = demo("alexia");
    	cout << *ps2 << *ps1 << endl;
    
    2. shared_ptr
    shared_ptr Realize the concept of shared ownership. Multiple smart pointers can point to the same object, and the object and its related resources will be released when the "last reference is destroyed".
    From name share It can be seen that resources can be shared by multiple pointers. It uses the counting mechanism to indicate that resources are shared by several pointers. You can use member functions
    use_count()To view the number of resource owners. Except through new Can also be passed in auto _ptr,  unique_ptr,weak_ptr To construct.
    When we call release()The current pointer releases resource ownership and the count is decremented by one. When the count equals 0, the resource is released.
    shared_ptr To solve the problem  auto_ptr Limitations on object ownership(auto_ptr Is exclusive) ,  
    A smart pointer that can share ownership is provided on the mechanism using reference counting.
    Member function:
    use_count Returns the number of references counted
    unique Returns whether it is exclusive ownership(use_count Is 1)
    swap Swap two shared_ptr object(That is, the objects owned by the exchange)
    reset Relinquishment of ownership of internal objects or change of ownership of objects, This causes the reference count of the original object to decrease
    get Return internal object(Pointer), Because it has been overloaded()method, So it's the same as using objects directly.
    as shared_ptrsp(new  int(1) );  sp And sp.get()Is equivalent
    
    3.weak_ptr
    weak_ptr Is a smart pointer that does not control the life cycle of an object, It points to a shared_ptr Managed objects.
    The memory of this object is managed by the strongly referenced shared_ptr. weak_ptr just
     Provides an access to management objects. weak_ptr The purpose of the design is to cooperate shared_ptr
     A smart pointer is introduced to assist shared_ptr work,  It can only come from one shared_ptr
     Or another weak_ptr Object construction, Its construction and deconstruction will not cause the increase or decrease of reference count.
    weak_ptr Is used to solve shared_ptr Deadlock problem in cross reference,If you say two
    shared_ptr Cross reference,Then the reference count of these two pointers can never drop to 0,Resources never
     Will be released. It is a weak reference to an object and does not increase the reference count of the object, and shared_ptr between
     Can be transformed into each other, shared_ptr It can be assigned directly, and it can be called lock Function to get
    shared_ptr. 
    
    class B;
    class A
    {public:
    shared_ptr<B> pb_;
    ~A()
    {
         cout<<"A delete
    ";
    }
    };
    class B
    {
    public:
    shared_ptr<A> pa_;
    ~B()
    {
        cout<<"B delete
    ";
    }
    };
    void fun()
    {
        shared_ptr<B> pb(new B());
        shared_ptr<A> pa(new A());
        pb->pa_ = pa;
        pa->pb_ = pb;
        cout<<pb.use_count()<<endl;
        cout<<pa.use_count()<<endl;
    }
    int main()
    {
        fun();
        return 0;
    }
    
    Can see fun In function pa,pb Reference each other. The reference count of the two resources is 2. When you want to jump out of the function
     Smart pointer when counting pa,pb During destruct, the two resource reference counts will be decremented by one, but the two reference counts are still
    1,Causes the resource not to be released when the function jumps out( A B If one of the destructors is not called
     Change to weak_ptr That's it. Let's put the class A Inside shared_ptr pb_;  Change to weak_ptr
    pb_;  The running results are as follows. In this case, the resource B There is only 1 at the beginning of the reference, when pb At the time of deconstruction, B My plan
     The number becomes 0, B Released, B Release will also make A Count minus one, and pa Destruct A Count of
     Minus one, then A The count of is 0, A Released.
    
    Note: cannot pass weak_ptr Methods that directly access objects, such as B Object has a method print(),
    We can't visit like this, pa->pb_ ->print();  english pb_It's a weak_ptr,You should put it first
     It translates into s hared_ ptr,For example: shared_ptr  p  =  pa->pb_.lock();  p->print();
    
  • About cast operators
    static_cast

    1.Conversion for non polymorphic types
    2.Do not perform runtime type checking (conversion security is not as good dynamic_cast)
    3.Typically used to convert numeric data types, such as float -> int)
    4.The pointer can be moved throughout the class hierarchy, the child class is converted to the parent class safe (up conversion), and the parent class is converted to the child class unsafe (because the child class
     (there may be fields or methods that are not in the parent class)
    

    dynamic_cast

    1.Conversion for polymorphic types
    2.Perform line runtime type check
    3.Applies only to pointers or references
    4.Conversion of ambiguous pointers will fail (return nullptr),But no exception is thrown
    5.The pointer can be moved throughout the class hierarchy, including up conversion and down conversion
    

    const_cast

    1.For deletion const,volatile and __unaligned Characteristics (if any) const int Type conversion to int (type) reinterpret_cast
    2.Simple reinterpretation for bits
    3.abuse reinterpret_cast Operators can be very risky. Unless the required transformation itself is low-level, you should- Use other mandatory
     One of the conversion operators.
    4.Allows any pointer to be converted to any other pointer type, such as char* reach int* or One_class* reach Unrelated_class* Or something
     Change, but it is not safe in itself)
    5.It also allows any integer type to be converted to any pointer type and vice versa.
    6.reinterpret_cast Operator cannot be discarded const,volatile or __unaligned characteristic.
    7.reinterpret_cast A practical use of is in hash functions, that is, by making two different values end almost differently with the same index
     To map a value to an index.
    

    bad_cast

    Because cast to reference type failed, dynamic_cast Operator raised bad_cast Abnormal.
    //bad_cast usage
    try {
        Circle& ref_circle = dynamic_cast<Circle&>(ref_shape);
    }
    catch (bad_cast b) {
        cout << "Caught: " << b.what();
    }
    
  • Talk about your understanding of copy constructor and assignment operator

    There are two differences between copy constructor and assignment operator overloading:
    1.The copy constructor generates a new class object, while the assignment operator cannot.
    2.Because the copy constructor directly constructs a new class object, you don't have to check whether the source object is consistent with the new object before initializing the object
     Same. The assignment operator requires this operation. In addition, in the assignment operation, if there is memory allocation in the original object, the memory should be released first.
    
    Note: when there are pointer type member variables in a class, be sure to override the copy constructor and assignment operator instead of using the default
    
  • In C + +, can the memory requested by malloc be released through delete? Can the memory requested with new use free?

    No, malloc /free Mainly for compatibility C,new and delete Can completely replace malloc/free of
    malloc/free All operation objects must be of definite size. And it can't be used on dynamic classes.
    new and delete Type check and size check will be performed automatically, malloc/free Constructors and destructors cannot be executed,
    So dynamic objects can't. Of course, in theory malloc The requested memory is available through delete Released.
    But it's not usually written like this. And there is no guarantee that everyone C++All can run normally.
    
  • Design a class that cannot be inherited with C + +

    template <typename T> class A 
    { 
       friend T; 
        private: 
         A() {} 
        ~A() {} 
    }; 
    class B : virtual public A<B> 
    { 
       public: 
        B() {} 
       ~B() {} 
    }; 
    class C : virtual public B 
    { 
       public: 
    	   C() {} 
        ~C() {} 
    }; 
    void main( void ) 
    { 
        B b; 
        //C c; 
        return; 
    } 
    
    //Note: the constructor is the key to inheritance implementation. Each time a subclass object is constructed, the constructor of the parent class is called first, and then its own.
    
  • C + + implements a String class by itself

#include <iostream>
#include <cstring>
using namespace std;
class String{
public:
    // Default constructor 
    String(const char *str = nullptr);
    // copy constructor 
    String(const String &str);
    // Destructor
    ~String();
    // String assignment function
    String& operator=(const String &str);
private:
    char *m_data;
    int m_size;
};
// Constructor
String::String(const char *str)
{
    if(str == nullptr)  // Bonus point: m_data plus NULL judgment
    {
        m_data = new char[1];   // Score point: for empty string, automatically apply for storage end flag '\ 0'
        m_data[0] = '\0';
        m_size = 0;
    }
    else
    {
    	m_size = strlen(str);
        m_data = new char[m_size + 1];
        strcpy(m_data, str);
    }
}
// copy constructor 
String::String(const String &str)   // Score point: the input parameter is const type
{
    m_size = str.m_size;
    m_data = new char[m_size + 1];  //Bonus point: m_data plus NULL judgment
    strcpy(m_data, str.m_data);
}
// Destructor
String::~String()
{
    delete[] m_data;
}
// String assignment function
String& String::operator=(const String &str)  // Score point: the input parameter is const
{
    if(this == &str)    //Scoring point: check self assignment
        return *this;
    delete[] m_data;    //Score point: release the original memory resources
    m_size = strlen(str.m_data);
    m_data = new char[m_size + 1];  //Bonus point: m_data plus NULL judgment
    strcpy(m_data, str.m_data);
    return *this;       //Score point: returns the reference of this object
}
  • Accessing private virtual functions of base classes

    #include <iostream.h> 
    class A
    { 
       virtual void g() 
       { 
          cout << "A::g" << endl; 
       } 
      private: 
       virtual void f() 
       { 
        	cout << "A::f" << endl; 
       } 
    }; 
    class B : public A 
    { 
       void g() 
       { 
          cout << "B::g" << endl; 
       } 
       virtual void h() 
       { 
          cout << "B::h" << endl; 
       } 
    }; 
    typedef void( *Fun )( void ); 
    void main() 
    { 
       B b; 
       Fun pFun; 
       for(int i = 0 ; i < 3; i++) 
       { 
          pFun = ( Fun )*( ( int* ) * ( int* )( &b ) + i ); 
          pFun(); 
       } 
    } 
    
    //Result output
    B::g 
    A::f 
    B::h 
    
    //Note: the interviewer's understanding of virtual function is investigated. It is difficult for a person who does not understand the virtual function to make this problem correctly. 
    //When learning object-oriented polymorphism, we must deeply understand the working principle of virtual function table.
    
  • Understanding of virtual functions and polymorphism

    The realization of polymorphism is mainly divided into static polymorphism and dynamic polymorphism. Static polymorphism is mainly overload, which has been determined at the time of compilation;
    Dynamic polymorphism is implemented by virtual function mechanism, which is bound dynamically during operation.
    For example, when the pointer of a parent type points to a subclass object, when the pointer of the parent class is used to call the virtual function in the overridden parent class in the subclass,
    The overridden function of the subclass will be called and declared as plus in the parent class virtual Keyword functions do not need to be added when overridden in subclasses virtual It's also a virtual function.
    
    Implementation of virtual functions: in classes with virtual functions, the first part of the class is a pointer to a virtual function table, which points to a virtual function table, in which the address of the virtual function is placed,
    The actual virtual function is in the code segment(.text)Yes.
    When a subclass inherits the parent class, it will also inherit its virtual function table. When a subclass rewrites the virtual function in the parent class, it will replace the address in the inherited virtual function table with the rewritten function address.				
    The use of virtual functions will increase the overhead of accessing memory and reduce efficiency.
    
  • Briefly describe the differences between class member function rewriting, overloading and hiding

    Rewriting and overloading are mainly different in the following points.

    1.Scope difference: the rewritten and rewritten functions are in two classes, while the overloaded and overloaded functions are in the same class.
    2.Parameter difference: the parameter list of rewritten function and rewritten function must be the same, while the parameter list of overloaded function and overloaded function must be different.
    3.virtual The difference: the overridden function in the overridden base class must have virtual Overloaded functions and overloaded functions can be modified virtual
     It can be modified or not.
    

    Hiding is different from overriding and overloading in the following points.

    Different from the scope of overloading: like overriding, hidden functions and hidden functions are not in the same class.
    Parameter difference: the parameter list of hidden function and hidden function can be the same or different, but the function name must be the same. When the parameter is not
     When the same, whether the parameters in the base class are virtual Modification, the functions of the base class are hidden, not rewritten.
    
    Note: Although overloading and coverage are the basis for realizing polymorphism, their technologies and purposes are completely different,
    Overrides are polymorphic in dynamic binding, while overloads are polymorphic in static binding.
    
  • What's the difference between a linked list and an array

    1.Storage form: array is a continuous space, and its length must be determined when declaring. Linked list is a discontinuous dynamic space with variable length
     A node needs to save adjacent node pointers.
    2.Data search: the linear search speed of the array is fast, and the offset address is directly used in the search operation. The linked list needs to retrieve nodes in order, which is inefficient.
    3.Data insertion or deletion: linked lists can quickly insert and delete nodes, while arrays may require a lot of data movement.
    4.Boundary crossing problem: the linked list does not have boundary crossing problem, and the array has boundary crossing problem.
    
    Note: when selecting an array or linked list data structure, you must select it according to your actual needs. Arrays are easy to query and linked lists are easy to insert and delete.
    The array saves space, but the length is fixed. Although the linked list becomes longer, it takes up more storage space.
    
  • Two stacks are used to realize the function of one queue

typedef struct node 
{ 
int data; 
node *next; 
}node,*LinkStack; 
//Create empty stack: 
LinkStack CreateNULLStack( LinkStack &S) 
{ 
 S = (LinkStack)malloc( sizeof( node ) ); // Apply for a new node 
 if( NULL == S) 
 { 
  printf("Fail to malloc a new node.\n");
  return NULL; 
 } 
 S->data = 0; //Initialize new node 
 S->next = NULL; 
 return S; 
} 
//Insert function of stack: 
LinkStack Push( LinkStack &S, int data) 
{ 
 if( NULL == S) //Inspection stack 
 { 
  printf("There no node in stack!"); 
  return NULL; 
 } 
 LinkStack p = NULL; 
 p = (LinkStack)malloc( sizeof( node ) ); // Apply for a new node 
 if( NULL == p) 
 { 
  printf("Fail to malloc a new node.\n"); 
  return S; 
 } 
 if( NULL == S->next) 
 { 
  p->next = NULL; 
 } 
 else 
 { 
  p->next = S->next; 
 } 
 p->data = data; //Initialize new node 
 S->next = p; //Insert new node 
 return S; 
} 
//Stack function: 
node Pop( LinkStack &S) 
{ 
 node temp; 
 temp.data = 0; 
 temp.next = NULL; 
 if( NULL == S) //Inspection stack 
 { 
  printf("There no node in stack!"); 
  return temp; 
 } 
 temp = *S; 
 if( S->next == NULL ) 
 { 
  printf("The stack is NULL,can't pop!\n"); 
  return temp; 
 } 
 LinkStack p = S ->next; //Node out of stack 
 S->next = S->next->next; 
 temp = *p; 
 free( p ); 
 p = NULL; 
 return temp; 
} 
//Double stack queue entry function: 
LinkStack StackToQueuPush( LinkStack &S, int data) 
{ 
 node n; 
 LinkStack S1 = NULL; 
 CreateNULLStack( S1 ); //Create empty stack 
 while( NULL != S->next ) //S out of stack into S1 
 { 
  n = Pop( S ); 
  Push( S1, n.data ); 
 } 
 Push( S1, data ); //New node stack 
 while( NULL != S1->next ) //S1 out of stack into S 
 { 
  n = Pop( S1 ); 
  Push( S, n.data ); 
 } 
 return S; 
} 

//Note: the function of one queue can be realized with two stacks. Can the function of one queue be realized with two queues? The result is negative,
//Because the stack is first in first out, connecting the two stacks together is first in first out. The queue is now first in first out. No matter how many are connected together, they are first in first out, and it is impossible to realize first in first out.
  • Underlying principle of vector

    vector The bottom layer is a dynamic array containing three iterators, start and finish Between them is the space range that has been used,
    end_of_storage Is the whole continuous space, including the tail of the spare space. When there is not enough space to load data( vec .push_back(val))When,
    Will automatically request another piece of larger space (1) . 5 Times or 2x), and then copy the original data to the new memory space,
    Then release the original space [vector Memory growth mechanism]. When released or deleted( vec.clear())When the data inside,
    The storage space is not released, but the data in it is emptied. Therefore, yes vec to r Once any operation of causes space reconfiguration,
    Point to the original vector All iterators will fail.
    
  • The difference between p reserve and resize in vector

    1. reserve It is directly expanded to the determined size, which can reduce the problem of multiple development and space release (optimization) push_back),Can
     Improve efficiency. Secondly, it can reduce the problem of copying data multiple times. reserve Just promise vector Space size in( capacity)least
     The size specified by the parameter is reached n. reserve()There is only one parameter.
    2. resize()You can change the size of the effective space and change the default value. capacity The size of the will also change. resize()Can have
     Multiple parameters.
    
  • The difference between size and capacity in vector

    1. size Represents the current vector How many elements are there in the( finish - start);
    2. capacity The function indicates how many elements it can hold in the allocated memory( end_of_storage - start);
    
  • The difference between erase method in vector and remove method in algorithm

    1. vector in erase Method actually deletes the element and the iterator cannot access it
    2. remove Simply move the element to the back of the container, and the iterator can still access it. because algorithm Operation through iterators
     Because you don't know the internal structure of the container, you can't really delete it.
    
  • Failure of the vector iterator

    1. When inserting an element into vector In, all iterators pointing to the original memory are invalidated due to memory reallocation.
    2. When an element in the container is deleted,The element pointed to by the iterator has been deleted, which also invalidates the iterator. erase Method returns the next
     A valid iterator, so when we want to delete an element, we need to it=vec.erase(it);. 
    
  • Release the memory of vector correctly (clear(), swap(), shrink())_ to_ fit())

    1. vec.clear(): Empty the contents without freeing memory.
    2. vector().swap(vec): Empty the contents and free the memory to get a new one vector. 
    3. vec.shrink_to_fit(): Request container to lower its capacity and size Match.
    4. vec.clear();vec.shrink_to_fit();: Empty contents and free memory.
    
  • The underlying principle of list

    1. list The bottom layer of is a two-way linked list. Using the linked list to store data will not store them in a whole continuous memory space. On the contrary,
    The storage space occupied by each element (also known as nodes) is independent and decentralized, and the linear relationship between them is maintained by pointers,Each insertion or
     Deleting an element configures or frees up an element space.
    2. list Random access is not supported. If a large number of inserts and deletions are required, random access is not concerned
    
  • Under what circumstances, use vector, list and deque

    1. vector You can store elements randomly (that is, you can directly calculate the element address through the formula without looking up one by one), but insert deletion in the non tail
     In addition to data, the efficiency is very low, suitable for simple objects, the number of objects changes little, and random access is frequent. Unless necessary, we choose to use it as much as possible
    vector Not deque,because deque Iterator ratio vector Iterators are much more complex.
    2. list Random storage is not supported. It is suitable for scenes with large objects, frequent changes in the number of objects, and frequent insertion and deletion, such as writing more and reading less.
    3. When you need to insert or delete from both ends, you need to select deque. 
    
  • priority_ Underlying principle of queue

    priority_queue: Priority queue, whose bottom layer is implemented by heap. In the priority queue, the queue head element must be the highest priority in the current queue
     The tall one.
    
  • Features of map, set, multiset and multimap

    1. set and multiset The elements are automatically sorted according to specific sorting criteria, set Duplicate elements are not allowed in, multiset Can be repeated.
    2. map and multimap take key and value Composed pair As an element, according to key The sorting criteria automatically sort the elements (because the red black tree is the same)
    Binary search tree, so map The default is by key Sorted), map Of elements in key No repetition is allowed, multimap Can be repeated.
    3. map and set The speed of addition, deletion, modification and query is logn,It is more efficient.
    
  • Underlying principles of map, set, multiset and multimap

    map,set ,multiset,multimap The underlying implementations of are all red and black trees, epoll The underlying data structure of the model is also a red black tree,
    linux In the system CFS The process scheduling algorithm also uses the red black tree.
    
    Characteristics of red black tree:
     - Each node is either red or black;
     - The root node is black;
     - Each leaf node is black;
     - If a node is red, its two sons are black;
     - All paths from each node to its descendants contain the same number of black nodes.
    
  • Why is the insertion and deletion efficiency of map and set higher than that of other sequence containers

    Because memory copy and memory movement are not required
    
  • Why does the previously saved iterator not become invalid after each map and set Insert?

    Because the insertion operation is just the exchange of node pointers, and the node memory has not changed. and iterator Like a pointer to a node, the memory does not change
     The pointer to memory does not change.
    
  • When the number of data elements increases (from 10000 to 20000), how does the search speed of the set of the map change?

    RB-TREE The binary search method is used, and the time complexity is logn,So when it increases from 10000 to 20000, the number of searches increases from log10000=14 Times to log20000=15 Times, just one more time.
    
  • Why is the insertion and deletion efficiency of map and set higher than that of other sequence containers, and the previously saved iterator will not become invalid after each insert?

    1.The storage node does not need memory copy and memory movement.
    2.The insertion operation is just the exchange of node pointers, and the node memory has not changed. and iterator Like a pointer to a node, the memory does not change and points to the inside
     The stored pointer will not change
    
  • Why can't map and set have a reserve function to pre allocate data like vector?

    stay map and set The internal storage is not the element itself, but the node containing the element. in other words map For internal use Alloc Not at all
    map<Key, Data, Compare, Alloc>Passed in from the parameter at the time of declaration Alloc. 
    
  • Why does the underlying implementation of set use red black tree instead of hash table?

    1. set The elements in the are sorted, the red black tree is ordered, and the hash is disordered
    2. If you are only looking for elements, you must choose the hash table, because the best lookup time complexity of the hash table is O(1),also
     If used set So the search time complexity has always been O(1),because set Duplicate elements are not allowed in. When searching for red and black trees
     The inter complexity is O(lgn)
    
  • hash_ What is the difference between map and map? When to use hash_map, when do you use map?

    1.Constructor: hash_map need hash function And equals the function, and map A comparison function (greater than or less than) is required.
    2.Storage structure: hash_map with hashtable For the bottom, and map with RB-TREE Is the bottom layer.
    3.In general, hash_map Find speed ratio map Fast, and the search speed is basically independent of the size of the data, which belongs to the constant level. and map of
     The search speed is logn Level. But not necessarily a constant log Small, and hash_map also hash function Time consuming.
    4.If efficiency is considered, especially when the element reaches a certain order of magnitude, use hash_map. 
    5.Consider memory or when the number of elements is small map. 
    
  • The problem of iterator failure

    Insert operation:
    1. about vector and string,If container memory is reallocated, iterators,pointers,references invalid; If not reassigned,
    So before the insertion point iterator Valid, after insertion point iterator invalid;
    2. about deque,If the insertion point is in Division front and back Other locations, iterators,pointers,references invalid; When we insert
     Element to front and back When, deque The iterator for failed, but reference and pointers Effective;
    3. about list and forward_list,be-all iterator,pointer and refercnce Effective. Delete operation:
    4. about vector and string,Before deleting a point iterators,pointers,references Effective; off-the-end Iterators always fail;
    5.about deque,If the deletion point is in Division front and back Other locations, iterators,pointers,references invalid; When we insert
     Element to front and back When, off-the-end Failure, others iterators,pointers,references Effective;
    6. about list and forward_list,be-all iterator,pointer and refercnce Effective.
    7. For associated containers map For example, if an element has been deleted, its corresponding iterator is invalid and should not be used again. No
     Will result in undefined behavior of the program.
    
  • STL thread unsafe condition

    1. When multithreading read-write and write operations are performed on the same container;
    2. Lock the container every time the member function of the container is called;
    3. Iterators returned in each container (for example, by calling begin or end)The container shall be locked during the lifetime of the;
    4. Lock the container during the execution of each algorithm called on the container.
    

Topics: C++ Interview