Guangjing Wang Assistant Professor @ USF

CPP Notes

2019-06-24

In this post, I will extend my notes to encompass C++, delving into the intricacies of this versatile programming language. C++ is widely used in the particle simulation computing project.

Random Generator

There are two types of mersenne_twister_engine, mt19937, mt19937_64. The version of this generator and compiler has nothing to do with the operating system version. However, to generate different distributions, the implementation of the compiler may be different. For a distribution, different C standards use different algorithm implementations. MSVC and the standard libstdc++ may use different algorithms, and external implementations can be used Boost.Random library.

Random_device provides a non-deterministic random number generation device. In the Linux implementation, it reads the /dev/urandom device. random_device provides the () operator, which returns a number between min() and max(). It can be seen as a true random number under Linux.

In a parallel program, each thread needs a private seed to generate random numbers, but the writing order of each thread is different. The writing order of the threads can be specified so that the random numbers generated can be reproduced.

Compile Template Class

Problem: After declares the header file in the template class of C++, it cannot be compiled normally and an undefined reference error is reported.

Reason: The space occupied by each object in C++ is determined at compile time. Before the template class is actually used, the compiler cannot know the space occupied by the object using the template type and what type it is applied to. This is also why the classes are called templates instead of generics?

Solution: All declarations and implementation must be written in the header file. For clarity, the implementation does not need to be written in the curly braces after the class, but can be written outside the class.

W/R String

char ch[]=”ab”;
string str=ch; // Convert character array to string
char buf[10];
string str=”ab”; 
strcpy(buf, str.c_str(), 10); // Convert string to char array

String objects cannot write string content to files through the write function;

string filename=”name”;
ofstream fout(filename.c_str()); //c_str() function returns a pointer to a regular C string, the content of which is the same as the string string. This is for compatibility with the C language;

char* state=”something”;
cout.write(state,i);

Binary storage vs. Text storage:

For characters, the binary representation is the same as the text representation. They are both binary representations of the ASCII code of the character. For numbers, when the value -2.324216e+07 is stored in text format, the 13 characters contained in the number will be stored. , the binary format refers to the computer’s internal representation of the stored value, that is to say, the computer does not store characters, but the 64-bit double representation of this value.

Class and Memory

class StringBad{
	private:
		char* str;
		static int num_strings;
}

str=new char[len+1]  
delete [] str 

In the above code, the use of char pointers to represent names means that no memory space is allocated for the string itself in the class declaration. Instead, new is used in the constructor to allocate space for the string, which avoids predefining characters in the class declaration. The length of the string; Secondly, declare the num_strings member as a static storage class. Static class members have a characteristic. No matter how many objects are created, all objects of these classes share a static member, so it can be used to record the total number of string objects. When using an object to initialize another object, the compiler will automatically generate a copy constructor, and the automatically generated constructor does not need to update the static member variable num_string.

Static member variables cannot be initialized in a class declaration because the declaration describes how to allocate memory, but does not allocate memory. Static class members exist separately and are not part of the object. If initialized in a header file, the program may include the header file in several other files, so there will be multiple copies of the initialization statement, causing an error.

Deleting an object can release the memory occupied by the object itself, but it cannot automatically release the memory pointed to by the pointers of the object members. Therefore, a destructor must be used, and delete corresponds to new.

Initialization

The constructor initialization list starts with a colon, followed by a comma-separated list of data members. Each data member is followed by an initializer in parentheses. The member initialization sequence of the initialization list: When C++ initializes class members, it is ** Initialize ** in the order they are declared, not in the order they appear in the initialization list.

CExample():a(0),b(8.8)

int F1(const char* pstr);

Using const modification when passing can ensure that the initial value of the passed parameter will not be modified through this pointer. Any attempt to modify *pstr inside the function will cause a compilation error.

Virtual Function

Virtual functions are implemented through a virtual function table, which is mainly an address table of virtual functions of a class. This table solves the problems of inheritance and overwriting and ensures that it truly reflects the actual function.

Function Object

The function object is a class type that can have its own data members; but it is used like a function and can be called in the same way as a function because the call operator () is overloaded. For example, define a data member bound, and assign a value to bound when initializing the function object. If you want to count the number of words with a length of more than 5, then bound=5; if it is more than 6, then bound=6, and so on. Specifically the code is as below:

class GT_cls{
	public:
		GT_cls (size_t val=0): bound(val){}
		bool operator() (const string &s){
			return s.size()>=bound;
		}
	private:
		std::string::size_type bound;
}

A *p; //p->play(); A is a structure pointer
A p; //p.play(); A is a structure variable

The initialization method of the structure and its constructor, the initialization method of the structure instance and the class instance are exactly the same. Both can be applied to the inheritance hierarchy. The difference is that the default members of the structure are public and the default members of the class are private; Data members with unspecified values are initialized to default values; if the data members in the structure are private or protected, or a constructor is provided, they must be initialized using the constructor.

Dynamic Library

.so under Linux is based on dynamic linking under Linux, similar to .dll files under Windows; usually, the link to the function library is placed during compilation, and all related object files and involved function library links are synthesized An executable file, in which these function libraries are called static libraries, usually have file names in the form of libxxx.a (or .so). When the program is running, it has nothing to do with the function library, because all the required functions have been copied to itself.

gcc -fPIC -c file1.c // -fPIC unlated to position
gcc -fPIC -c file2.c
gcc -shared libxxx.so file1.o file2.o

If the loader can’t find the shared library, we didn’t install it in a standard location, so we need to help the loader. We have two options: use the environment variable LD_LIBRARY_PATH or rpath:

  1. The compiler will first search for the libxxx.so file in the path folder. If it is not found, it will continue to search for libxxx.a. During the running of the program, you also need to tell the system where to find your dynamic link library file. Under UNIX, this is achieved by defining an environment variable named LD_LIBRARY_PATH. Just assign path to this variable. The csh command is:
    setenv LD_LIBRARY_PATH   your/full/path/to/dll
    
  2. g++ compilation option, -Wl,rpath= specifies the location of the dynamic link library;
    g++ -o main main.cpp -I /usr/local/include/python/: set g++ head file location
    

To use a dynamic link library for implicit calls, you first need to let the compiler check some syntax and definitions during compilation. This is basically the same as the utility of static libraries, using the -Lpath and -lxxx labels, the library file path is specified with the -L identifier, and the library name is specified with the -l identifier.

gcc file1.o file2.o -Lpath -lxxx -o program.exe

Float and Double

Float, double precision and numerical range in C language: float 32 bits, including 1 sign bit, 8 exponent bits, and 23 mantissa bits. The precision is determined by the number of digits in the mantissa. Floating point numbers are stored in memory according to scientific notation. Float: 2^23^=8388608, a total of seven digits, that is, up to 7 valid digits, and 6 digits are absolutely guaranteed; double: 2^52^, the accuracy is guaranteed to be 16 digits.

Define Sort

  1. Define the sorting function and declare the external comparison function. The comparison function is written outside the class or declared as a static function; This is because when the comparison function is used as a member function of the class, it has a this pointer by default, which is inconsistent with the sorting function type required by the sort function;
    static bool less(const student& s1, const student s2)
    sort(stuVec.begin(), stuVec.end, less);
    
  2. Overloaded comparison operators
    bool operator <(const student& s1, const student& s2);
    
  3. Declare comparison class
    struct less{
     bool operator()(const student& s1, const student& s2);
    }
    

Delete

The difference between delete and delete[] in C++ is that delete is used to release the memory pointed to by a single object pointer allocated by new, and delete[] is used to release the memory pointed by the object array pointer allocated by new. For basic types, there is basically no difference between the two. For class, delete ptr is used to release the memory pointed to by ptr, delete[] rg is used to release the memory pointed to by rg, and the destructor of each object in the array is also called one by one. Especially for classes that use system resources, they must be released using the destructor.

Others

  • C++ function to find the maximum and minimum value of an array

      #include<algorithm>
      int a[5]={1,2,3,5,-1}
      max_element(a, a+5) // find the position of the largest element, which is a pointer,get value by *max_element
    
  • Split string by spaces

      string result;
      vector<string> res;
      stringstream input(str);
      while(input>>result){
          res.push_back(result);
      }
    
  • The atoi function string in C language is converted into an integer;

  • 1«2: Shift the binary code of 1 to the left by 2 bits. Shifting one bit to the left is equivalent to multiplying the number by 2;

  • Compilation error, jump to case label [-fpermissive]

    Reason: In the Switch case statement, this kind of compilation error will occur when defining variables in the case. The compiler thinks that this way of writing will incorrectly define the variable.

    Solution: Move the definition of variables out of switch case; do not define variables under if or case.


Content