There's strictly no warranty for the correctness of this text. You use any of the information provided here at your own risk.
C++ was designed by Bjarne Stroustrup in the early 1980s. It was first published in 1985. Since then it has received many revisions, there was especially a major update in 2011.
C++ is an object-orientated language, based on C. In the early days (up to 1983) it was called "C with Classes".
But although C++ is compatible to C, it is considered to be a different language than C.
If you write a program in C++, and have the choice to either use C-constructions or C++-constructions, it is suggested to prefer the latter ones.
Here's a timeline, when these common programming languages were created, respectively first released:
C | Around 1970 |
C++ | Around 1980 to 1985 |
Perl | 1987 |
Python | 1991 |
Java | 1995 |
Obviously, C++ has some constructions in common with C. But with its classes, it sometimes also feels a bit similar to Python. Python is of course an interpreted language, and easier to use than C++. On the other hand, C++-code runs faster. So it may be a good idea to write prototypes of object-oriented programs in Python first, and then translate them to C++ later.
It seems, throughout the years there have been many changes to the language. "C++23" is the recent version at the moment, but "C++26" is already planned. Especially since the update of 2011, C++ seems to be a lot easier to use than earlier versions. Older tutorials may show deprecated syntax that has been replaced by much more convenient language constructions.
So when reading a tutorial that is too old, you may get the wrong impression, that programming in C++ is much more difficult than it actually is today.
Especially explicitly managing memory (which is essential in C) seems only rarely be needed in C++ any more, which makes things a lot easier.
Here's a tutorial I can recommend.
I'm learning C++ relatively late, when I'm already acquainted with Perl, Python and C. So I'm keeping this page relatively small. I may be assuming some knowledge of certain constructions that are also common in the other languages, and are therefore described on the pages about those. So this page may not be for the absolute beginner, who isn't familiar with any of the other programming languages mentioned.
The compiler-executable for C++ in the gcc-distribution is called "g++".
If you have a file "h.cpp", you can run
g++ h.cpp
and get a file "a.out", which you can run then with
./a.out
C++ has evolved over the years. There has been a major update in 2011.
If code doesn't compile, the reason may be, that modern constructions of this update were used. Then it may help to compile with:
g++ -std=c++11 source.cpp
Here's a "Hello World" in C++:
#include <iostream> using namespace std; int main() { cout << "Hello World." << endl; return 0; }
"cout" is the program's output stream. "cout" means "character output". So characters are redirected there with "<<".
"cout" and "endl" are part of the namespace "std" and could also be written as "std::cout" and "std::endl". If you wrote them that way, you wouldn't need the "using namespace ..."-line above.
It's also possible to define your own namespaces. You can use single variables from that namespace by just using "using" (not "using namespace"), followed by two colons, and then the name of the variable. Like that:
using my_namespace::a;Or you can introduce the whole namespace with "using namespace" followed by the name of your namespace:
#include <iostream> using namespace std; namespace my_namespace { int a = 1; int b = 2; } int main () { using namespace my_namespace; cout << a << endl; cout << b << endl; return 0; }
In addition to C's syntax:
/* ..... */in C++ you can use:
// ...
Then all characters after the double-slashes in a line are considered to be comment.
The following constructions work just like in C:
#include <iostream> using namespace std; int main() { int i; for (i = 0; i <= 10; i++) { if (i == 5) { continue; } cout << i << endl; } i = 0; while (i < 10) { cout << i << endl; if (i == 5) { break; } i++; } return 0; }
It's also possible to iterate over "collections" (such as vectors or STL-arrays, see below) with:
for (int i : vec) { ... }
If "vec" contains strings, you'd have to write respectively:
for (string i : vec) { ... }
In this case, you can also use the "auto"-feature, which tries to identify the data type of a variable from its context:
for (auto i : vec) { ... }
In C++, there's a datatype "string". Such strings are objects, so they have methods. These methods can be called using the "."-operator (like in Python). Useful methods are:
If a string is equal to another string can also simply be checked with the "=="-operator.
There can be "string constants" in the code, that aren't assigned to any variable.
Single characters in a string are of datatype 'char' and can be accessed by using square brackets like in "a[0]". This can also be used for replacing single characters in a string.
#include <iostream> using namespace std; int main() { string a = "Hello"; cout << a.length() << endl; cout << a.substr(1, 3) << endl; string b = "Hello"; if (a.compare(b) == 0) { cout << "a is \"" << b << "\"." << endl; } cout << a[1] << endl; a[1] = 'x'; cout << a << endl; cout << a.find("l", 0) << endl; return 0; }
"cin", the counterpart to "cout", can be used to ask the user for an integer (or a double / floating point number) on the console.
int a; cin >> a;
If the user should enter a string, the function "getline(cin, [string])" has to be used.
This is a nice little program from a good Perl-book (Laura Lemay: "Sams Teach Yourself Perl in 21 Days"), I can recommend. If you get to this program and can run it, you already know some of the constructions, a programming-language uses:
#include <iostream> using namespace std; int main() { // Cookie Monster string cookies; while (cookies != "COOKIES") { cout << "I want COOKIES: "; getline(cin, cookies); } cout << "Mmmm. COOKIES." << endl; }
This is actually not much more difficult than in Perl or Python.
Pointers are basically declared and used as they are in C.
The keyword for null-pointers is "nullptr" (instead of "NULL" in C).
If you want to store a known amount of data of a single type, you can use C-arrays or STL-arrays, that are described in the next section.
Vectors can be used, when a dynamic list is required. Then, the line
#include <vector>
has to be added. And to make it all work, in most cases the code has to be compiled with:
g++ -std=c++11 source.cpp
Vectors are declared with the keyword "vector", followed by the type of data to be stored in the vector included between "lesser than" and "greater than"-characters, followed by the name of the vector:
vector<int> my_vector;
In "-std=c++11", they can be initialized with values in curly brackets (similar to C-arrays):
vector<int> my_vector = {1, 2, 3};
Useful methods of vectors are:
If you want to store strings, floats and doubles together in a vector, you can declare the vector for "string" altogether, and convert the strings that store the numbers with the functions "stoi()", "stof()" and "stod()" (found in namespace "std") later.
Vectors can also be arguments to functions. Here's an example:
#include <iostream> #include <vector> // Compile with: g++ -std=c++11 source.cpp using namespace std; void printIntVector(vector<int> vec) { int i; int vecsize = vec.size(); cout << "["; for (i=0; i < vecsize; i++) { cout << vec[i]; if (i < vecsize - 1) { cout << ", "; } } cout << "]" << endl; } int main() { vector<int> items = {1, 2, 3}; items.push_back(100); printIntVector(items); items.pop_back(); printIntVector(items); return 0; }
If not specified otherwise, the vector is passed to a function by value. That means, that for use in the function a copy of the vector is created, and the function just operates on that copy.
If you want to pass the vector by reference instead, an "&" has to be added in the function's declaration. Then the function operates on the same vector, that exists outside the functions, and changes made to that vector inside the function also effect the vector in the rest of the program:
void printIntVector(vector<int> &vec) {...}
A vector can be assigned to another vector (with "="). This creates a copy of the vector.
Here I translated the example about lists from my Perl-page to C++:
#include <iostream> #include <vector> using namespace std; int main() { // Initialize a vector of strings: vector<string> fruits = {"apple", "banana"}; // Add an element at the end of the vector: fruits.push_back("peach"); // Create a loop, that iterates through the vector (printing it). for (auto i : fruits) { cout << i << endl; } cout << endl; // Get the last element of the vector, then remove it from there: string l = fruits.back(); fruits.pop_back(); int fruitslen = fruits.size(); cout << fruitslen << endl; cout << l << endl; // Get the first element of the vector, then remove it from there: l = fruits.front(); fruits.erase(fruits.begin()); fruitslen = fruits.size(); cout << fruitslen << endl; cout << l << endl; // Add an element at the beginning of the vector: fruits.insert(fruits.begin(), "peach"); fruits.insert(fruits.begin(), "apple"); // Iterate through the vector again: cout << endl; for (auto i : fruits) { cout << i << endl; } cout << endl; // Get the number of elements of the vector: fruitslen = fruits.size(); cout << fruitslen << endl << endl; // Erase an element in the middle of the vector: fruits.erase(fruits.begin() + 1); // Add an element in the middle of the vector: fruits.insert(fruits.begin() + 1, "cherry"); // Iterate through the vector again: cout << endl; for (auto i : fruits) { cout << i << endl; } cout << endl; // Access an element by element number. // Notice that the element numbers are in the range from 0 to the number of elements minus 1, // so "fruits.at(1)" is the second element of the list: cout << fruits.at(1) << endl; fruits.at(1) = "strawberry"; cout << fruits.at(1) << endl; return 0; }
Similar to vectors, static arrays can be defined in a C++-way using the "Standard Template Library" (STL). These STL-arrays are more comfortable than C-arrays. The line
#include <array>
has to be added, and compiling with
g++ -std=c++11 source.cpp
is probably also needed.
Then you can define an array of 10 elements with:
array<int,10> items = {1, 2, 3};
It has a ".size()" function and (unlike C-arrays) can be passed directly to functions like vectors (by value or - with "&" - by reference):
void printIntSTLArray(array<int,10> arr) {...}
There isn't a push-method for STL-arrays, but elements can be written directly like in:
arr[9] = 25;
A quick example:
#include <iostream> #include <array> using namespace std; void printArray(array<int,3> arr) { for (auto i: arr) { cout << i << endl; } } int main() { array<int,3> arr = {1, 2, 3}; printArray(arr); return 0; }
To implement a data type with pairs of keys and values that are not in a specific order (something that would be called a "hash" in Perl or a "dictionary" in Python), there is the data type called "unordered_map" in C++. Here's an example:
#include <iostream> #include <unordered_map> using namespace std; int main() { unordered_map<string, int> a = { {"One", 1}, {"Two", 2}, {"Three", 3} }; cout << a["One"] << endl; return 0; }
In C++, you can also have vectors of vectors (and so on):
#include <iostream> #include <vector> // Compile with: g++ -std=c++11 using namespace std; void printIntVector(vector<int> vec) { int i; int vecsize = vec.size(); cout << "["; for (i=0; i < vecsize; i++) { cout << vec[i]; if (i < vecsize - 1) { cout << ", "; } } cout << "]" << endl; } int main() { vector<vector<int> > items = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; for (vector<int> i : items) { printIntVector(i); } return 0; }
Notice, there has to be the space character between the two ">" in "vector<vector<int> > ...", which is a bit odd. But the compiler says so.
Memory can be managed by using the keywords "new" and "delete" in combination with a pointer.
Here's an example:
#include <iostream> using namespace std; int main() { char *p = new char[10]; p[0] = 'H'; p[1] = 'e'; p[2] = 'l'; p[3] = 'l'; p[4] = 'o'; p[5] = '\0'; printf("%s\n", p); delete(p); return 0; }
So "new" and "delete" basically work similar to the functions "malloc()" and "free()" in C.
But it seems, in recent versions of C++ it's not that often necessary to manage memory that way. As shown in the chapters above, for example strings (C++-strings), vectors and STL-arrays can be used without explicitly managing memory. As we'll see in the next chapter, this also applies to classes and objects.
What object oriented programming (that is programming with classes and objects) is about, I've already explained on my site "Object-Oriented Programming in Perl Made Easy".
Actually, classes in C++ are defined and used in a rather similar way.
There's a special function in the class, called a "constructor". It is called, when an object is instantiated. In Python this special function is called "__init__", in Perl it's called "new". In C++, constructors have the same name as the class itself.
When you want to use a constructor that doesn't expect any arguments, you call the constructor at instantiation without any arguments - and also without any brackets. That's a rather unusual function-call.
The code inside a class is divided by two special lines:
private:
and
public:
The attributes and methods in the "private" part can only be accessed from inside the class. While the code in the "public" part can also be accessed from other classes or functions.
If for example you try to access a private variable of a class directly from the function "main()" of the program (that is from outside the class), you get an error at compilation time.
I'm giving the special lines "private:" and "public:" an indentation level of two characters, so that the declarations of attributes and methods inside the class can start at the ordinary indentation level of four characters. But I don't know, if that's common to do.
As the code inside the class is by default private, unless it is written below the "public:" statement, the statement "private:" can also be left out. But I suggest writing it anyway to make things clearer.
The "private:" section can also be left empty, so this code is valid and compiles:
class Test { private: // pass public: Test() { } }; int main() { Test t = Test(); return 0; }
The constructor function (which has the same name as the class itself) should be in the "public"-part of the class (like it is in the example above).
When a class in C++ is defined, it automatically receives a special pointer called "this". The attributes and methods of the class are normally defined and used without this pointer. But they can also be accessed through it when necessary. For example, an "int"-variable called "a" can be accessed inside the class like this:
this->a
The attributes can be declared either in the "private"-part or in the "public"-part, depending on whether they should be accessed from outside the class or not.
The constructor function (which is in the "public"-part of the class) can also receive ordinary function arguments. The values of these arguments can then be assigned to the attributes.
Just like you'd do for example in Python:
#!/usr/bin/python # coding: utf-8 class Test: def __init__(self, argument): self.attribute = argument t = Test("a_test") print t.attribute
In C++, you'd do:
#include <iostream> using namespace std; class Test { private: // pass public: string attribute; Test(string argument) { attribute = argument; } }; int main() { Test t("a_test"); cout << t.attribute << endl; return 0; }
And in Perl:
#!/usr/bin/perl use warnings; use strict; package Test { sub new { my $classname = shift; my $self = {}; my $argument = shift; $self->{attribute} = $argument; return bless($self, $classname); } } my $t = Test->new("a_test"); print $t->{attribute} . "\n";
The syntaxes may be a bit different, but the principles and the results are rather similar. Though C++-code may run quite a bit faster.
Here's the first of two OOP-examples on my Perl-page (example number 2 and 3), now translated to C++:
#include <iostream> using namespace std; // OOP-example 2 class Lamp { private: string name; string state; int lightintensity; public: Lamp(string name, int light) { // To distinguish between the attribute and the function parameter: this->name = name; lightintensity = light; state = "off"; } void switchOn() { state = "on"; cout << "'" << name << "' is on at " << lightintensity << " Watt." << endl; } void switchOff() { state = "off"; cout << "'" << name << "' is off." << endl; } void newLightBulb(int light) { if (state == "on") { cout << "Light bulb can not be changed. "; cout << "First, '" << name << "' has to be switched off." << endl; } else { lightintensity = light; cout << "Light bulb in '" << name << "' has been changed. "; cout << "The new bulb has " << light << " Watt." << endl; switchOn(); } } }; int main() { Lamp lamp1("First Lamp", 50); Lamp lamp2("Second Lamp", 40); lamp1.switchOn(); lamp2.switchOn(); lamp2.newLightBulb(100); lamp2.switchOff(); lamp2.newLightBulb(100); return 0; }
And the second one:
#include <iostream> using namespace std; // OOP-example 3 class Lamp { private: int lightintensity; string name; public: Lamp(int lightintensity = 40, string name = "Default lamp") { this->lightintensity = lightintensity; this->name = name; } void showLightIntensity() { cout << "'" << name << "' has a light bulb with "; cout << lightintensity << " Watt." << endl; } }; int main() { Lamp lamp1(11, "1"); lamp1.showLightIntensity(); // This is a weird function call (no brackets): Lamp lamp2; lamp2.showLightIntensity(); return 0; }
There has to be a semicolon after the closing bracket of the class-definiton, similar to struct-definitions in C.
Notice, that you can also use a pointer on an object:
Lamp *pLamp = &lamp1;
If a subclass should inherit from a superclass, the following syntax can be used:
class Subclass : public Superclass { ... };
Here we're writing some lines of text to a file called "schiller.txt", then we read in the contents of that file into a vector and print it:
#include <iostream> #include <vector> #include <fstream> using namespace std; void printStringVector(vector<string> vec) { int i; int vecsize = vec.size(); cout << "["; for (i=0; i < vecsize; i++) { cout << "\"" << vec[i] << "\""; if (i < vecsize - 1) { cout << ", "; } } cout << "]" << endl; } int main() { string filename = "schiller.txt"; // Commented out for security reasons. If you want to write the file // "schiller.txt", delete the characters "/*" and "*/": /* ofstream fh; fh.open(filename); vector<string> schiller = {"Und blicket sie lange verwundert an.", "Drauf spricht er: 'Es ist euch gelungen,", "Ihr habt das Herz mir bezwungen,", "Und die Treue, sie ist doch kein leerer Wahn.'"}; for (string i: schiller) { fh << i << endl; } fh.close(); */ vector<string> a; string buf; ifstream fh2(filename); while (getline(fh2, buf)) { a.push_back(buf); } fh2.close(); printStringVector(a); return 0; }
Notice, that you have to use "getline(fh, [string]);" to read a line from a file, just like you have to use getline(), when reading a line from "cin". If you just did "fh2 >> buf", it would read the file word by word.