// helloworld.cpp
#include <iostream>
int main() {
std::cout << "Hello, world!\n";
return 0;
}
#include
with no .h
and library differsg++ -std=c++17 -o helloworld helloworld.cpp
// The following two are equivalent
std::cout << "\n" << std::flush;
std::cout << std::endl;
When streaming things to stdout
, things are stored in a buffer. things are sent to terminal when the buffer is flushed. std::endl
sends a \n
and also do a flush. For devices with limited computational power, \n
is better as it gives better performance.
#include <string>
int main() {
std::string s = "";
s[0];
}
Runtime error is compiler-dependent. This error might crash and also might be ignored.
const
#include <iostream>
#include <vector>
int main() {
const int i = 0; // i is an int
i++; // not allowed
std::cout << i << '\n'; // allowed
const std::vector<int> vec;
vec[0]; // allowed
vec[0]++; // not allowed
vec.push_back(0); // not allowed
}
int i = 1;
int j = 2;
int& k = i;
k = j; // This does not make k reference j instead of i. It just changes the value.
std::cout << "i = " << i << ", j = " << j << ", k = " << k << '\n';
Reference is similar to C, but without the need of using ->
to access the value. It is like an alias to the original object. Reference is always const
and is not null.
const
int i = 1;
const int& ref = i;
std::cout << ref << '\n';
i++; // This is fine
std::cout << ref << '\n';
ref++; // This is not
const int &i = 1; // this works
int &i = 1; // this does not
When references to literal value, it must be const
.
const int j = 1;
const int& jref = j; // this is allowed
int& ref = j; // not allowed
The value of the object cannot be modified through the const
reference but the original object can still be modified. Reference to const
must also be const
.
std::optional<T>
, std::vector<T>
, std::unordered_map<KeyT, ValueT>
for example.
#include <unordered_map>
#include <vector>
// The following items are all function DECLARATIONS
// Not allowed - type templates are not types
std::vector GetVector();
// std::vector<int> and std::vector<double> are valid types.
std::vector<int> GetIntVector();
std::vector<double> GetDoubleVector();
// So is combining types
std::vector<std::unordered_map<int, std::string>> GetVectorOfMaps();
std::vector<int>
and std::vector<string>
are 2 different types, unlike Javaauto
auto i = 0; // i is an int
std::vector<int> fn();
auto j = fn(); // j is std::vector<int>
// Pointers
int i;
const int *const p = i;
auto q = p; // const int*
auto const q = p;
// References
const int &i = 1; // int
auto j = i; // int
const auto k = i; // const int
auto &r = i; // const int&
Compiler will deduct the actual type of auto
. Take exactly the type on the right-hand side but strip off the top-level const and &.
string Rgb(short r = 0, short g = 0, short b = 0);
Rgb();// rgb(0, 0, 0);
Rgb(100);// Rgb(100, 0, 0);
Rgb(100, 200); // Rgb(100, 200, 0)
Rgb(100, , 200); // error
Default arguments are like Python, but arguments cannot be specified when calling it. And if one parameter uses default argument, all other parameters also need to have a default value. So void test(int a = 0, int b);
does not work.
void swap(int& x, int& y) {
int tmp;
tmp = x;
x = y;
y = tmp;
}
With the pass by reference, to use it, just need to call it without pointer styles:
swap(i, j);
Pass by reference is useful when:
Pass by reference is not compatible with C as it does not support it.
void Print(double d); // (1)
int Print(std::string s); // (2)
void Print(char c); // (3)
Print(3.14); // call (1)
Print("hello World!"); // call (2)
Print('A'); // call (3)
C++ function overloading is very similar to Java function overloading. Return types are ignored when overloading.
Top-level const
is ignored but low-level const
is not.
// Top-level const ignored
Record Lookup(Phone p);
Record Lookup(const Phone p); // redefinition
// Low-level const not ignored
Record Lookup(Phone &p); (1)
Record Lookup(const Phone &p); (2)
Phone p;
const Phone q;
Lookup(p); // (1)
Lookup(q); // (2)
constexpr
// Beats a #define any day.
constexpr int max_n = 10;
// This can be called at compile time, or at runtime
constexpr int ConstexprFactorial(int n) {
return n <= 1 ? 1 : n * ConstexprFactorial(n - 1);
}
constexpr int tenfactorial = ConstexprFactorial(10);
// This may not be called at compile time
int Factorial(int n) {
return n <= 1 ? 1 : n * Factorial(n - 1);
}
// This will fail to compile
constexpr int ninefactorial = Factorial(9);
A variable that can be calculated at compile time is calculated at compile time. A function whose inputs are known at compile time will run at compile time.
As the computations are done at compile time, the run time of the program will be faster and less computation will be needed at run time.
// path/to/BUILD
cc_library(
name = "hello_world",
srcs = ["hello_world.cpp"],
hdrs = ["hello_world.h"],
deps = []
)
cc_library(
name = "printer",
srcs = ["printer.cpp"]
hdrs = ["printer.h"],
deps = [
# If it's declared within the same build
# file, we can skip the directory
":hello_world"
]
)
Like make, bazel is another open source build system.
srcs
hdrs
deps
cc_library
A piece of code that can’t run on its own, but can be depended upon by other filescc_binary
The srcs should have a main function, has no headers, cannot be testedcc_test
Works very similar to a binary, semantic difference