Background:
C++ was built on top of C, which provided a small set of built-in types: numbers, characters, arrays. As the language evolved, concepts like structures, classes, and enumerations were added — they became user-defined types.
Issue:
The data type in a program determines how much memory a variable will occupy, how it will be initialized, copied, destroyed, compared, etc. Built-in types have behavior defined by the standard, while user-defined types require explicit definition of all aspects. Errors in managing user-defined types can lead to crashes, memory leaks, unfair comparisons of objects, and so on.
Solution:
Built-in types include int, float, double, char, bool, and other "primitives." User-defined types are any structures, classes, or unions created by you. For complex tasks, user-defined types must be implemented with correct semantics for copying, comparison, and resource management.
Code example:
// Built-in type int x = 5; // User-defined type struct Point { double x, y; }; Point a = {1.0, 2.0}; // Class with resources class MyFile { public: MyFile(const std::string& fn) : f(fopen(fn.c_str(), "r")) {} ~MyFile() { if (f) fclose(f); } private: FILE* f; };
Can user-defined types behave completely like built-in types (for example, be compared using == "out of the box")?
No, the == comparison works by default only starting from C++20 via defaulted operator==, before that explicit definition was required.
Is it possible not to implement a copy constructor and destructor for a class that holds only a raw pointer (int, FILE, etc.)?**
No, in this case, copying will be "shallow" by default, which will lead to memory/resource leaks or double free. You need to implement the "Rule of Five."
Will the value of a structure be initialized to zero by default (Point p;)?
No, a local structure may be uninitialized, and the memory content is random. Use explicit initialization.
Negative case:
A file wrapper class did not implement a destructor. The program worked until it started processing thousands of files without closing descriptors.
Pros: less code, simplified appearance Cons: resource leaks, unstable behavior
Positive case:
A class implements RAII — the file is opened in the constructor, closed in the destructor, copying is forbidden.
Pros: reliability, safety, clean interface Cons: need to remember the "Rule of Five" and write more code