Type Inference Related
- auto: Automatic type inference, used to simplify the specification of types; especially useful when type strings are long, simplifying the writing.
{ // Simplified iterator std::list<int> tAuto = { 1,2,3,4 }; for (auto it = tAuto.begin(); it != tAuto.end(); it++) { } std::function<void(int)> funPtr = nullptr; // Simplified long type writing. Automatic type inference. Lambda expressions will be automatically inferred as std::function<xxx> type auto xx = [=](int) { return 1; }; funPtr = xx;}
- decltype(exp): Expression type inference
int x = 10;const int cx = 20;int& rx = x;decltype(x) a; // intdecltype(cx) b = 30; // const intdecltype(rx) c = x; // int&// Infer expression typedecltype(x + 1.0) d; // doubledecltype((x)) e = x; // int& (note the effect of parentheses)// Particularly useful in template programmingtemplate<typename T, typename U>auto add(T t, U u) -> decltype(t + u) { return t + u; }
Smart Pointer Related
- nullptr: Null pointer, used to replace NULL and 0, clearly indicating it is a pointer type.
int* p1 = nullptr; // Clearly indicates a null pointerint* p2 = 0; // Traditional way, not clear enoughint* p3 = NULL; // Macro definition, C style
Class Design Keywords
- default: Explicitly indicates that the compiler should generate the default function
- delete: Prohibits a function, i.e., forbids certain operations, such as prohibiting copying, prohibiting assignment, etc.
- final: Prohibits inheritance or overriding
- override: Explicitly overrides a virtual function
//Base1 is prohibited from being overloaded //class Deriver1 : public Base1 {} is not allowedclass Base1 final {public:};class Base {public: Base() = default; // Use default constructor Base(const Base&) = default; ~Base() = default; virtual void testFun(int a) {}; // Virtual function virtual void testFun2(double a) {};};class Derived : public Base {public: Derived() = default; // Default constructor Derived(const Derived&) = delete; // Prohibit copying Derived& operator=(const Derived&) = delete; // Prohibit assignment operation // Override testFun() void testFun(int a) override{ } //void testFun(double a) override{} // This writing cannot compile // testFun2() is overridden and cannot be overridden by subsequent inheritors (final) void testFun2(double a) override final{ }};
constexpr
- constexpr: Compile-time constant.
- For variables, must be initialized at definition
- For functions, return values and parameters must be literal types (such as basic types, pointers), and the function body must be computable at compile time. Also, non-constexpr functions cannot be called within constexpr functions
- For debugging, cannot step into the function using F11 (because it is computed at compile time)
// Compile-time calculation of n's factorial
constexpr int factorial(int n) { return (n <= 1) ? 1 : n * factorial(n - 1);}// Compile-time string length calculationconstexpr size_t string_length(const char* str) { return (*str == '\0') ? 0 : 1 + string_length(str + 1);}// Using in a classclass Circle {private: double radius;public: constexpr Circle(double r) : radius(r) {} constexpr double getArea() const { return 3.14159 * radius * radius; }};// Compile-time constant, commonly used for compile-time calculationsinline void TestConstExpr(){ constexpr int size = 100; constexpr double pi = 3.14159; // Compile-time array size int arr[size]; // Valid, size is a compile-time constant // constexpr function - may be evaluated at compile time constexpr int fact5 = factorial(5); // Compile-time calculation constexpr size_t len = string_length("hello"); // len = 5 constexpr Circle c(2.0); constexpr double area = c.getArea(); // Compile-time calculation std::cout << "area = " << area;}
Debugging result image:
noexcept:
Does not throw exceptions. Move constructors are usually marked as noexcept
// Ensure the function does not throw exceptionsvoid safe_function() noexcept { // This function guarantees not to throw exceptions }// Move constructor is usually marked as noexceptclass MyType {public: MyType(MyType&& other) noexcept { // Move resources } MyType& operator=(MyType&& other) noexcept { // Move assignment return *this; }};
static_assert:
- Compile-time assertion, checks if a certain condition is not met at compile time, stops compilation, reports a compile error. If the condition is met, compilation passes, no extra code is generated, no runtime overhead.
- Commonly used in template programming for type parameter constraints, type or value checks.
Example, checks if the template function outputs a string type, compilation reports an error
// Define a template function that does not support std::string operationstemplate <typename T>T TestStatic_Assert(T a, T b) { static_assert(!std::is_same<T, std::string>::value, "is string"); return a + b;} // Compile-time input string, reports error.//TestStatic_Assert<std::string>("aaa", "bbb");
typeid
typeid() returns the name of the variable type at runtime or the type of the variable, the return value is a type_info object. If the class type has virtual functions, typeid() returns the dynamic type of the expression (i.e., if a base class pointer points to a derived class, it returns the type of the derived class).
Note:
- typeid() is similar to the keyword and sizeof().
- To use typeid, include <typeinfo> header file.
- typeid() has a certain performance overhead, especially in polymorphic cases
- typeid() requires explicit types, cannot be used for void types
type_info objects cannot be copy-constructed or assigned. type_info provides the following operations
- name(): returns the readable name of the type
- == and != operators: used to determine if two type_info objects are equal or not
- raw_name(): raw name
inline void TestTypeId() { int a = 10; std::cout << " base int = " << typeid(a).name() << std::endl; Base* b1 = new Base(); Base* de = new Derived(); //std::type_info tiB1 = typeid(b1); std::cout << " base1 = " << typeid(b1).name() << " raw_name = "<< typeid(b1).raw_name() << " size_t" << typeid(b1).hash_code()<< std::endl; std::cout << " base1 = " << typeid(*de).name() << " raw_name = " << typeid(*de).raw_name() << " size_t" << typeid(*de).hash_code() << std::endl;}
Purely for personal learning and understanding, welcome to add WeChat for mutual discussion and improvement. WeChat ID is as follows:
