ProgrammingMid-level C++ Developer

What are built-in (primitive) and user-defined types in C++, how do they differ, and why is this important when designing complex programs?

Pass interviews with Hintsage AI assistant

Answer.

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; };

Key features:

  • Built-in types: fast, trivial copying, known size and behavior.
  • User-defined types: needed to describe complex entities, can manage resources, require implementation of constructors and destructors.
  • Control of operation semantics (+, =, ==), conversions, and other aspects of behavior.

Trick questions.

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.

Common mistakes and anti-patterns

  • Neglecting explicit initialization of user-defined types.
  • Not implementing destructor and copy constructor for classes with dynamic memory.
  • Trying to manage resources using built-in types (e.g., raw pointers).

Real-life example

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