In the vast ocean of programming languages, C++ stands out with its powerful capabilities and flexibility. Since it was developed by Bjarne Stroustrup at Bell Labs in 1979, C++ has gradually become the language of choice for high-performance applications and system programming. It not only inherits the efficient characteristics of the C language but also introduces the concept of object-oriented programming, making software development more structured and maintainable.
C++ has widespread applications ranging from game development, graphics processing, to building operating systems and large software systems. With its rich standard library and powerful template mechanism, C++ enables developers to write efficient and reusable code. This blog will take you through the basic concepts of C++, its development history, the importance of learning this language, and its application scenarios. Whether you are a beginner or an experienced developer, C++ will offer you new perspectives and skills for your programming journey.
1. Origins and Development History of C++
1.1 Origins
The origins of C++ can be traced back to 1979 when Bjarne Stroustrup developed it at Bell Labs. Faced with the limitations of existing languages like C for complex software development, he introduced object-oriented features on top of C in 1983, officially naming it C++. The language gradually gained adoption in academia and industry and became a teaching language in many universities.
1.2 C++ Version Updates
In 1989, the standardization of C++ began, with the first draft of the standard presented in 1994, which introduced the Standard Template Library (STL), greatly enhancing C++'s functionality. After several discussions, the ANSI/ISO standard was officially released in 1998, solidifying C++'s position in programming languages. Since then, C++ has undergone multiple updates such as C++11, C++14, C++17, and C++20, continuing to evolve to meet modern development needs.
2. Applications of C++ in the Workplace
C++ is used in many fields, including server-side applications, game engines, machine learning engines, audio and video processing, embedded software, telecom equipment, financial applications, core libraries, operating systems, compilers, infrastructure, tools, hardware interaction, and more.
Large system software development: such as compilers, databases, operating systems, and browsers.
Audio and video processing: Common open-source libraries and solutions include FFmpeg, WebRTC, Mediasoup, ijkplayer. C++ is the main technology stack for audio and video development.
PC client development: Typically involves developing desktop software for Windows, such as WPS. The technology stack is generally C++ and QT. QT is a cross-platform C++ graphical user interface (GUI) framework.
Server-side development: Large applications and high-concurrency backend services for network connections. Java is also widely used here, while C++ is employed for areas requiring higher performance, such as game services, streaming services, and high-frequency trading services.
Game engine development: Many game engines are developed using C++. Game development requires understanding C++ fundamentals, data structures, graphics knowledge, and mastering game engines and frameworks. Open-source engine implementations like UE4 and Cocos2d-x can be studied.
Embedded development: Involves embedding a computing control board into devices like smart wristbands, cameras, robots, smart speakers, door control systems, and car systems. Embedded development includes application and driver development.
Machine learning engines: Many core machine learning algorithms are implemented in C++, with Python used for higher-level wrappers. If you want to work on machine learning system development, learning C++ is essential.
Testing development/Testing: Every company has both development and testing teams. Testing includes test development and functional testing. Test developers typically use tools like Selenium and JMeter, designing test cases and writing scripts for automated testing and performance testing.
3. Recommendations for Getting Started with C++
3.1 Reference Documents
Note: The first link is not the official C++ documentation, as it only updates to C++11 but presents content in a more readable format. The latter two are official C++ documentation in Chinese and English, respectively, and provide comprehensive information updated to the latest C++ standards, though they are not as easy to read as the first.
3.2 Recommended Books
Beginner Level
Programming: Principles and Practice Using C++ by Bjarne Stroustrup
C++ Primer by Stanley B. Lippman, Josée Lajoie, Barbara E. Moo
Accelerated C++: Practical Programming by Example by Andrew Koenig and Barbara E. Moo
Intermediate Level
Effective C++ by Scott Meyers
More Effective C++ by Scott Meyers
The C++ Standard Library: A Tutorial and Reference by Nicolai M. Josuttis
Advanced Level
The C++ Programming Language by Bjarne Stroustrup
C++ Concurrency in Action by Anthony Williams
Modern C++ Design by Andrei Alexandrescu
C++ Templates: The Complete Guide by David Vandevoorde, Nicolai M. Josuttis, Doug Gregor
Specialized Topics
C++17 in Detail by Bartłomiej Filipek (for modern C++ standards)
Effective Modern C++ by Scott Meyers (focus on C++11 and C++14)
A Tour of C++ by Bjarne Stroustrup (overview of modern C++ features)
This list covers foundational learning, advanced techniques, and specialized areas such as concurrency, templates, and modern C++ standards.
4. C++ First Program
4.1 C Language Approach
C++ is compatible with most of the C language syntax, so a C program like "Hello World" can still run in C++. In C++, the file extension must be changed to .cpp
, and the compiler will recognize it and call the C++ compiler. In Linux, g++
should be used instead of gcc
.
#include<stdio.h> int main() { printf("hello world!"); return 0; }
4.2 C++ Approach
#include<iostream> int main() { std::cout << "hello world" << std::endl; return 0; }
5. Namespaces
5.1 Why Use Namespaces
In C/C++, there are many variables, functions, and classes, and their names are all in the global scope, which may cause conflicts. The purpose of using namespaces is to localize the names of identifiers to avoid naming conflicts or pollution. The namespace
keyword addresses this issue.
5.2 Defining a Namespace
A namespace is a mechanism in C++ for organizing code. It allows related classes, functions, variables, etc., to be grouped together in a namespace to avoid name conflicts and improve readability. It is defined with the namespace
keyword as follows:
namespace NamespaceName { int variable; void function() { // Function implementation } }
In this example, we define a namespace called NamespaceName
containing an integer variable and a function.
5.3 Key Features
Scope Independence: A namespace creates an independent scope where the members defined within it do not interfere with members in the global scope or other namespaces.
Resolving Name Conflicts: Different namespaces can define the same variable, function, etc., without conflict. For example,
namespace A { void func(); }
andnamespace B { void func(); }
can coexist.Nesting: Namespaces can be nested to better organize code.
namespace Outer { namespace Inner { void innerFunction() { // Implementation } } }
Cross-file Sharing: The same namespace can be defined across multiple files in a project and will be treated as a single namespace without conflict.
Standard Library Namespace: All elements of the C++ standard library are included in the
std
namespace, such asstd::cout
andstd::vector
.
5.4 Usage Example
To use a member from a namespace:
Using the scope resolution operator:
NamespaceName::function();
Using
using
declaration:
using namespace NamespaceName; function(); // Direct call
Note: The using
directive expands all members of a namespace, which is not recommended for larger projects due to potential conflicts. It is best to use using
for specific, conflict-free members in smaller programs.
6. C++ Input & Output
Concept Overview
<iostream>
stands for "Input Output Stream" and is the standard library for input and output streams. It defines standard input and output objects.std::cin
is an object of theistream
class, mainly used for the standard input stream of narrow characters (of typechar
).std::cout
is an object of theostream
class, mainly used for the standard output stream of narrow characters.std::endl
is a function that, when inserted into a stream, adds a newline character and flushes the buffer.<<
is the stream insertion operator, and>>
is the stream extraction operator. (In C, these operators are also used for bitwise left/right shifts.)Using C++ input and output is more convenient, as there is no need to manually specify formats like
printf
/scanf
. C++ input and output can automatically detect variable types (this is essentially achieved through function overloading, which we will discuss later). The most important feature is that C++ streams better support input and output for user-defined types.IO streams involve classes and objects, operator overloading, inheritance, and many other object-oriented concepts. Since we haven’t covered these topics yet, we can only briefly introduce how to use C++ IO streams here. We will have a dedicated section later to discuss the IO stream library in detail.
cout
,cin
,endl
, etc., belong to the C++ Standard Library, which is contained within a namespace calledstd
(for "standard"). Therefore, we must use the namespace to access them.In daily practice, we can use
using namespace std
, but in real project development, it’s not recommended.We didn’t include
<stdio.h>
, butprintf
andscanf
can also be used, as they are indirectly included when we include<iostream>
. This is true for Visual Studio compilers; other compilers may throw errors.Code Example
#define _CRT_SECURE_NO_WARNINGS #include<iostream> using namespace std; int main() { // To improve IO efficiency in scenarios with high IO demands, such as certain competitive programming problems involving large inputs, add the following three lines: ios_base::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); int a = 10; double b = 1.1; char c = 'a'; cout << a << " " << b << " " << c << endl; std::cout << a << " " << b << " " << c << std::endl; scanf_s("%d%lf", &a, &b); printf("%d %lf\n", a, b); // Automatically detect variable types cin >> a >> b >> c; cout << a << " " << b << " " << c << endl; return 0; }
7. Default Parameters
DefinitionDefault parameters in C++ refer to the default values specified for parameters when declaring or defining a function. If no arguments are provided for these parameters during function calls, the default values are automatically used. This feature enhances the flexibility and ease of use of functions. Here's a detailed introduction to C++ default parameters:
Fully defaulted means all parameters are given default values.
Partially defaulted means some parameters are given default values. C++ requires that partial default parameters be assigned in a continuous order from right to left; there can be no gaps between default values.
Default parameters can be fully defaulted or partially defaulted.
When calling a function with default parameters, C++ requires arguments to be passed from left to right; you cannot skip over any arguments.
When function declarations and definitions are separated, default parameters can only appear in the function declaration, not in both the declaration and definition.
Code Example
#define _CRT_SECURE_NO_WARNINGS #include <iostream> using namespace std; // Fully defaulted void Func1(int a = 10, int b = 20, int c = 30) { cout << "a = " << a << endl; cout << "b = " << b << endl; cout << "c = " << c << endl << endl; } // Partially defaulted void Func2(int a, int b = 10, int c = 20) { cout << "a = " << a << endl; cout << "b = " << b << endl; cout << "c = " << c << endl << endl; } int main() { Func1(); // Equivalent to func1(10, 20, 30) Func1(1); // Equivalent to func1(1, 20, 30) Func1(1, 2); // Equivalent to func1(1, 2, 30) Func1(1, 2, 3); // Equivalent to func1(1, 2, 3) Func2(100); // Equivalent to func2(100, 10, 20) Func2(100, 200); // Equivalent to func2(100, 200, 20) Func2(100, 200, 300); // Equivalent to func2(100, 200, 300) return 0; }
8. Function Overloading
Basic Concept of Function OverloadingIn C++, function overloading allows us to define multiple functions with the same name, but the parameter lists (number, type, or order of parameters) must differ. The compiler determines which function to call based on the arguments passed.
The core idea behind function overloading is the difference in parameter lists. Here are some examples of overloaded functions:
void print(int num); void print(double num); void print(const char* str);
In the examples above, we have defined three print
functions, each with different parameter lists, so they are treated as separate functions.
Rules of Function Overloading
Different number of parameters: Functions can have different numbers of parameters.
Different parameter types: Functions can have the same number but different types of parameters.
Different parameter order: If the number and types of parameters are the same, but their order differs, they can also be overloaded.
Code Example
#define _CRT_SECURE_NO_WARNINGS #include<iostream> using namespace std; // 1. Different parameter types int Add(int x, int y) { cout << "int Add(int x, int y)" << endl; return x + y; } double Add(double x, double y) { cout << "double Add(double x, double y)" << endl; return x + y; } // 2. Different number of parameters void fun() { cout << "void fun()" << endl; } void fun(int a) { cout << "void fun(int a)" << endl; } // 3. Different parameter order void func(int a, double b) { cout << "void func(int a, double b)" << endl; } void func(double a, int b) { cout << "void func(double a, int b)" << endl; } int main() { Add(10, 20); Add(10.1, 20.2); fun(); fun(10); func(10, 2.2); func(10.1, 22); return 0; }