C++: Difference between revisions
No edit summary |
|||
(32 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
== References == |
== References == |
||
See also [[C|C references]]. |
See also [[C|C references]] and [[C / C++]]. |
||
=== Links === |
|||
<ul> |
|||
;C++ language |
|||
<li>[http://www.cplusplus.com/reference/ www.cplusplus.com — C++ Reference]</li> |
|||
* '''http://en.cppreference.com/''' (can be freely downloaded, or installed as package {{deb|cppreference-doc-en-html}}, view with ''DevHelp''). |
|||
* Including [http://www.cplusplus.com/reference/clibrary/ C Language Library] |
|||
* |
* '''[http://www.cplusplus.com/reference/ www.cplusplus.com]''' — C++ Reference |
||
: Including [http://www.cplusplus.com/reference/clibrary/ C Language Library] |
|||
: and ... [http://www.cplusplus.com/reference/iostream/ IOStream Library] |
|||
<li> [http://www.research.att.com/~bs/hopl-almost-final.pdf Evolving a language in and for the real world: C++ 1991-2006, Bjarne Stroustrup] (pdf)</li> |
|||
: Create a local copy with: |
|||
<li> manpage <tt>stl-manual</tt> (from SGI)</li> |
|||
<source lang="bash"> |
|||
# Make a local copy of www.cplusplus.com - use option -P http://proxy:port if needed |
|||
sudo mkdir httrack |
|||
sudo chown www:www-data httrack/ |
|||
cd httrack/ |
|||
sudo su www -c "httrack http://www.cplusplus.com/ -W -O /var/www/httrack -I0 -n -d -%v \ |
|||
'-www.cplusplus.com/forum/*' '-www.cplusplus.com/src/*' '-www.cplusplus.com/member/*' \ |
|||
'-www.cplusplus.com/user/*' '-www.cplusplus.com/contact*' -P 127.0.0.1:8118" |
|||
</source> |
|||
;STL |
|||
* See cppreference.com and cplusplus.com above. |
|||
* [http://www.sgi.com/tech/stl/ SGI — Standard Template Library Programmer's Guide] |
|||
* '''{{deb|libstd++-x.x-doc}}''' package |
|||
<source lang=bash> |
|||
sudo apt install libstd++-6-doc |
|||
man std::vector |
|||
</source> |
|||
;Miscellaneous |
|||
* [http://www.parashift.com/c++-faq/ C++ FAQ] |
|||
* [http://www.research.att.com/~bs/hopl-almost-final.pdf Evolving a language in and for the real world: C++ 1991-2006, Bjarne Stroustrup] (pdf) |
|||
: manpage <tt>stl-manual</tt> (from SGI) |
|||
<source lang="bash"> |
<source lang="bash"> |
||
sudo apt-get install stl-manual |
sudo apt-get install stl-manual |
||
ln -s /usr/share/doc/stl-manual/html /var/www/sgi # Now the manual is available at http://localhost/sgi |
ln -s /usr/share/doc/stl-manual/html /var/www/sgi # Now the manual is available at http://localhost/sgi |
||
</source> |
</source> |
||
</ul> |
|||
=== |
=== Books === |
||
* [http://www.informit.com/store/product.aspx?isbn=0201633612 Design Patterns: Elements of Reusable Object-Oriented Software] |
|||
<source lang="bash"> |
|||
# Make a local copy of www.cplusplus.com - use option -P http://proxy:port if needed |
|||
== C++ Standards == |
|||
httrack http://www.cplusplus.com/ -W -O /var/www -%v "-www.cplusplus.com/forum/*" "-www.cplusplus.com/src/*" "-www.cplusplus.com/member/*" |
|||
=== C++11 === |
|||
;References |
|||
* https://blog.smartbear.com/development/the-biggest-changes-in-c11-and-why-you-should-care/ |
|||
* https://en.wikipedia.org/wiki/C%2B%2B11 |
|||
* http://www.stroustrup.com/C++11FAQ.html |
|||
;Range-based for loop |
|||
C++11 introduces [http://en.cppreference.com/w/cpp/language/range-for range-based for loops]: |
|||
<source lang="c"> |
|||
std::vector<int> v = {0, 1, 2, 3, 4, 5}; |
|||
const auto& cv = v; |
|||
int a[] = {0, 1, 2, 3, 4, 5}; |
|||
for (const int& i : v) // access by const reference |
|||
for (auto i : v) // access by value, the type of i is int |
|||
for (auto&& i : v) // access by forwarding reference, the type of i is int& |
|||
for (auto&& i : cv) // access by f-d reference, the type of i is const int& |
|||
for (int n : {0, 1, 2, 3, 4, 5}) // the initializer may be a braced-init-list |
|||
for (int n : a) // the initializer may be an array |
|||
</source> |
</source> |
||
Use <code>std::as_const(x)</code> to prevent copy-on-write: |
|||
<source lang="c"> |
|||
struct cow_string { /* ... */ }; // a copy-on-write string |
|||
cow_string str = /* ... */; |
|||
// for(auto x : str) { /* ... */ } // may cause deep copy |
|||
for(auto x : std::as_const(str)) { /* ... */ } |
|||
</source> |
|||
This is not to be confused with the [http://en.cppreference.com/w/cpp/algorithm/for_each <code>for_each</code>] algorithm in STL. |
|||
;Lambda expressions |
|||
A lambda expression has the form: <code>[capture](parameters)->return-type {body}</code>. |
|||
<source lang="c"> |
|||
int main() |
|||
{ |
|||
char s[]="Hello World!"; |
|||
int Uppercase = 0; //modified by the lambda |
|||
for_each(s, s+sizeof(s), [&Uppercase] (char c) { |
|||
if (isupper(c)) |
|||
Uppercase++; |
|||
}); |
|||
cout<< Uppercase<<" uppercase letters in: "<< s<<endl; |
|||
} |
|||
</source> |
|||
;Automatic Type Deduction <code>auto</code> and <code>decltype</code> |
|||
Use keyword <code>auto</code> to infer the type of an object automatically: |
|||
<source lang="c"> |
|||
auto x=0; //x has type int because 0 is int |
|||
auto c='a'; //char |
|||
auto d=0.5; //double |
|||
auto national_debt=14400000000000LL;//long long |
|||
</source> |
|||
The new operator <code>decltype</code> takes an expression and returns its type: |
|||
<source lang="c"> |
|||
const vector<int> vi; |
|||
typedef decltype (vi.begin()) CIT; |
|||
CIT another_const_iterator; |
|||
</source> |
|||
Note that the reference type of <code>auto&&</code> depends on the the reference given (as per ''reference collapsing'' rule [http://en.cppreference.com/w/cpp/language/reference]) [https://stackoverflow.com/questions/13230480/what-does-auto-tell-us]: |
|||
<source lang="c"> |
|||
A& & becomes A& |
|||
A& && becomes A& |
|||
A&& & becomes A& |
|||
A&& && becomes A&& |
|||
</source> |
|||
For short, <code>auto&&</code> is an ''universal reference'' (like <code>T&&</code> in templates) that just binds to anything [https://stackoverflow.com/questions/13230480/what-does-auto-tell-us]. |
|||
;Uniform Initialization Syntax |
|||
C++ has at least four different initialization notations, some of which overlap. |
|||
Parenthesized initialization looks like this: |
|||
<source lang="c"> |
|||
std::string s("hello"); |
|||
int m=int(); //default initialization |
|||
</source> |
|||
You can also use the <code>=</code> notation for the same purpose in certain cases: |
|||
<source lang="c"> |
|||
std::string s="hello"; |
|||
int x=5; |
|||
</source> |
|||
For POD aggregates, you use braces: |
|||
<source lang="c"> |
|||
int arr[4]={0,1,2,3}; |
|||
struct tm today={0}; |
|||
</source> |
|||
Finally, constructors use member initializers: |
|||
<source lang="c"> |
|||
struct S { |
|||
int x; |
|||
S(): x(0) {} }; |
|||
</source> |
|||
C++11 cleans up this mess with a uniform brace notation: |
|||
<source lang="c"> |
|||
class C |
|||
{ |
|||
int a; |
|||
int b; |
|||
public: |
|||
C(int i, int j); |
|||
}; |
|||
C c {0,0}; //C++11 only. Equivalent to: C c(0,0); |
|||
int* a = new int[3] { 1, 2, 0 }; //C++11 only |
|||
class X { |
|||
int a[4]; |
|||
public: |
|||
X() : a{1,2,3,4} {} //C++11, member array initializer |
|||
}; |
|||
</source> |
|||
In C++11 you can initialize containers intuitively: |
|||
<source lang="c"> |
|||
// C++11 container initializer |
|||
vector<string> vs={ "first", "second", "third"}; |
|||
map singers = |
|||
{ {"Lady Gaga", "+1 (212) 555-7890"}, |
|||
{"Beyonce Knowles", "+1 (212) 555-0987"}}; |
|||
</source> |
|||
Similarly, C++11 supports in-class initialization of data members: |
|||
<source lang="c"> |
|||
class C |
|||
{ |
|||
int a=7; //C++11 only |
|||
public: |
|||
C(); |
|||
}; |
|||
</source> |
|||
;Deleted and Defaulted Functions |
|||
''Defaulted'' functions instruct the compiler to provide the default implementation for these functions: |
|||
<source lang="c"> |
|||
struct A |
|||
{ |
|||
A()=default; //C++11 |
|||
virtual ~A()=default; //C++11 |
|||
}; |
|||
</source> |
|||
The opposite of a defaulted function is a deleted function. To disable copying, declare these two special member functions =delete: |
|||
<source lang="c"> |
|||
struct NoCopy |
|||
{ |
|||
NoCopy & operator =( const NoCopy & ) = delete; |
|||
NoCopy ( const NoCopy & ) = delete; |
|||
}; |
|||
NoCopy a; |
|||
NoCopy b(a); //compilation error, copy ctor is deleted |
|||
</source> |
|||
;nullptr |
|||
<code>nullptr</code> is strongly-typed: |
|||
<source lang="c"> |
|||
void f(int); //#1 |
|||
void f(char *);//#2 |
|||
//C++03 |
|||
f(0); //which f is called? |
|||
//C++11 |
|||
f(nullptr) //unambiguous, calls #2 |
|||
</source> |
|||
;Delegating Constructors |
|||
In C++11 a constructor may call another constructor of the same class: |
|||
<source lang="c"> |
|||
class M //C++11 delegating constructors |
|||
{ |
|||
int x, y; |
|||
char *p; |
|||
public: |
|||
M(int v) : x(v), y(0), p(new char [MAX]) {} //#1 target |
|||
M(): M(0) {cout<<"delegating ctor"<<endl;} //#2 delegating |
|||
}; |
|||
</source> |
|||
;Rvalue References |
|||
Rvalue references can bind to rvalues, e.g. temporary objects and literals [http://en.cppreference.com/w/cpp/language/reference]. |
|||
The primary reason for adding rvalue references is move semantics. |
|||
you can declare a move constructor and a move assignment operator like this: |
|||
<source lang="c"> |
|||
class Movable |
|||
{ |
|||
Movable (Movable&&); //move constructor |
|||
Movable&& operator=(Movable&&); //move assignment operator |
|||
}; |
|||
</source> |
|||
;[http://en.cppreference.com/w/cpp/utility/move <code>std::move</code>] |
|||
<code>std::move</code> is used to indicate that an object t may be "moved from", i.e. allowing the efficient transfer of resources from t to another object. |
|||
<source lang="c"> |
|||
// Simple move constructor |
|||
A(A&& arg) : member(std::move(arg.member)) // the expression "arg.member" is lvalue |
|||
{} |
|||
// Simple move assignment operator |
|||
A& operator=(A&& other) { |
|||
member = std::move(other.member); |
|||
return *this; |
|||
} |
|||
</source> |
|||
''Reference collapsing'' rule [http://en.cppreference.com/w/cpp/language/reference]: |
|||
<source lang="c"> |
|||
typedef int& lref; |
|||
typedef int&& rref; |
|||
int n; |
|||
lref& r1 = n; // type of r1 is int& |
|||
lref&& r2 = n; // type of r2 is int& |
|||
rref& r3 = n; // type of r3 is int& |
|||
rref&& r4 = 1; // type of r4 is int&& |
|||
</source> |
|||
;More stuff |
|||
* C++11 Standard Library |
|||
* Threading Library |
|||
* New Smart Pointer Classes |
|||
* New C++ Algorithms |
|||
=== C++14 === |
|||
;References |
|||
* http://www.drdobbs.com/cpp/the-c14-standard-what-you-need-to-know/240169034 |
|||
* https://en.wikipedia.org/wiki/C%2B%2B14 |
|||
* https://www.quora.com/What-are-the-key-new-features-in-the-C++-14-standard |
|||
;Return type deduction |
|||
<code>auto</code> can be used as function return type. Most useful when combined with templates, or to avoid cascade of API changes if changing some object internal type. |
|||
<source lang="c"> |
|||
auto getvalue() |
|||
{ |
|||
return 1.4; |
|||
} |
|||
</source> |
|||
;Generic lambdas |
|||
These are lambdas using <code>auto</code> as parameter type: |
|||
<source lang="c"> |
|||
// Here we make in fact a named-lambda |
|||
auto adder = [](auto op1, auto op2){ return op1 + op2; }; |
|||
</source> |
|||
This is the loose equivalent of creating a template function. |
|||
;Initialized Lambda Captures |
|||
Now lambda parameter can be initialized: |
|||
<source lang="c"> |
|||
auto y = [&r = x, x = x+1]()->int {...} |
|||
</source> |
|||
This allows for the ''move'' semantic in lambdas: |
|||
<source lang="c"> |
|||
#include <memory> |
|||
#include <iostream> |
|||
int main() |
|||
{ |
|||
std::unique_ptr<int> p(new int); |
|||
int x = 5; |
|||
*p = 11; |
|||
auto y = [p=std::move(p)]() { std::cout << "inside: " << *p << "\n";}; |
|||
y(); |
|||
std::cout << "outside: " << *p << "\n"; |
|||
return 0; |
|||
} |
|||
</source> |
|||
;The <code>[[deprecated]]</code> attributes |
|||
<source lang="c"> |
|||
[[deprecated("Consider using something other than cranky")]] |
|||
int cranky() |
|||
{ |
|||
return 0; |
|||
} |
|||
</source> |
|||
Handling is compiler specific. |
|||
;Binary Literals and Digit Separators |
|||
Now we can use <code>0b</code> to construct binary literals (like <code>0x</code> for hex). |
|||
<source lang="c"> |
|||
int val = 0b11110000; |
|||
</source> |
|||
Use <code>'</code> to separate digit group (will not change the value): |
|||
<source lang="c"> |
|||
int mask = 0b1000'0001'1000'0000; |
|||
float salary = 300'000.00; |
|||
</source> |
|||
;Miscellaneous |
|||
* Variable templates |
|||
* [https://stackoverflow.com/questions/37514509/advantages-of-using-make-unique-over-new-operator <code>make_unique</code>] |
|||
<source lang="c"> |
|||
auto up = make_unique<LongTypeName>(args) # Better than calling new without disclaimer |
|||
</source> |
|||
=== C++17 === |
|||
* [http://www.modernescpp.com/index.php/cpp17-core C++17 - What's New in the Core Language?] |
|||
* https://github.com/tvaneerd/cpp17_in_TTs/blob/master/ALL_IN_ONE.md |
|||
: Description of C++17 features, in 100 source code examples. |
|||
* https://en.wikipedia.org/wiki/C%2B%2B17 |
|||
=== C++0x (old stuff) === |
|||
* [http://www2.research.att.com/~bs/C++0xFAQ.html C++0x - the next ISO C++ standard (Bjarne Stroustrup)] |
|||
* [http://gcc.gnu.org/projects/cxx0x.html C++0x support in GCC] |
|||
* [http://www.softwarequalityconnection.com/2011/06/the-biggest-changes-in-c11-and-why-you-should-care/ The Biggest Changes in C++11 (and Why You Should Care)] |
|||
;auto_ptr deprecated |
|||
*[http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=158 Using auto_ptr To Automate Memory Management] |
|||
*[http://www.informit.com/content/images/020163371X/autoptrupdate/auto_ptr_update.html history of auto_ptr] |
|||
;unique_ptr and shared_ptr |
|||
*[http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=400 Using unique_ptr, Part I]<br/>Basically, ''unique_ptr'' '''permits''' ''move from rvalues'' with copy syntax using a move constructor (which binds to rvalues), while '''blocking''' the ''copy from lvalues'' by making the copy constructor (which binds to lvalues) private: |
|||
<source lang="cpp"> |
|||
template <class T> |
|||
class unique_ptr |
|||
{ |
|||
public: |
|||
unique_ptr(unique_ptr&& u); // rvalues bind here |
|||
private: |
|||
unique_ptr(const unique_ptr&); // lvalues bind here |
|||
}; |
|||
</source> |
|||
*http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=239 The shared_ptr Class] |
|||
;rvalue references (and ''move'' semantics) |
|||
*[http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=310 The rvalue Reference Proposal, Part I] |
|||
== Benchmark == |
== Benchmark == |
||
Line 34: | Line 395: | ||
== Nested Classes == |
== Nested Classes == |
||
See [http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8a.doc%2Flanguage%2Fref%2Fcplr061.htm Nested classes on ibm.com]. |
See [http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8a.doc%2Flanguage%2Fref%2Fcplr061.htm Nested classes on ibm.com]. |
||
== Virtual destructors == |
|||
Rule of thumb: ''make your destructor virtual if your class has any virtual functions.'' |
|||
Virtual destructors are needed when a derived class is explicitly deleted via <code>delete</code>, but using a reference/pointer to a base class. |
|||
== Patterns == |
|||
=== Resource Allocation Is Initialization (RAII) === |
|||
Reference: |
|||
* [http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization Resource Acquisition Is Initialization] |
|||
* [http://www.stroustrup.com/bs_faq2.html#finally Bjarne Stroustrup's explanation about absence of <code>finally</code> block] |
|||
From [http://stackoverflow.com/questions/161177/does-c-support-finally-blocks-and-whats-this-raii-i-keep-hearing-about Kevin on stackoverflow.com]: |
|||
''The idea is that an object's destructor is responsible for freeing resources. When the object has automatic storage duration, the object's destructor will be called when the block in which it was created exits — even when that block is exited in the presence of an exception''. |
|||
=== Concurrency === |
|||
* [https://awesomekling.github.io/MutexProtected-A-C++-Pattern-for-Easier-Concurrency/ MutexProtected: A C++ Pattern for Easier Concurrency] |
|||
* [https://clang.llvm.org/docs/ThreadSafetyAnalysis.html Clang - Thread Safety Analysis] |
|||
== Tips == |
== Tips == |
||
=== Scoped enums === |
|||
Use ''scoped enums'' to specify the underlying (storage) type for enums (available since c++11, ie. gcc/clang option <code>-std=c++11</code>): |
|||
<source lang=cpp> |
|||
typedef enum : unsigned char { zero, one, two } enum8_t; |
|||
typedef enum : unsigned short { zero16, one16, two16 } enum16_t; |
|||
assert (sizeof(enum8_t) == 1); |
|||
assert (sizeof(enum16_t) == 2); |
|||
</source> |
|||
=== Finally blocks === |
|||
From [http://stackoverflow.com/questions/161177/does-c-support-finally-blocks-and-whats-this-raii-i-keep-hearing-about stackoverflow.com]: |
|||
<source lang=cpp> |
|||
int * array = new int[10000000]; |
|||
try { |
|||
// Some code that can throw exceptions |
|||
// ... |
|||
throw std::exception(); |
|||
// ... |
|||
} catch (...) { |
|||
// The finally-block (if an exception is thrown) |
|||
delete[] array; |
|||
// re-throw the exception. |
|||
throw; |
|||
} |
|||
// The finally-block (if no exception was thrown) |
|||
delete[] array; |
|||
</source> |
|||
Note that the finally block may throw an exception, hence discarding the original exception. |
|||
To avoid the double <code>delete</code>: |
|||
<source lang=cpp> |
|||
std::exception_ptr e; |
|||
try { |
|||
/*try block*/ |
|||
} |
|||
catch (...) { |
|||
/*finally block*/ |
|||
e = std::current_exception(); |
|||
} |
|||
if (e) { // e evaluates to 'false' if no exception! |
|||
std::rethrow_exception(e); |
|||
} |
|||
</source> |
|||
=== Miscellaneous === |
|||
{| class=wikitable width="100%" |
{| class=wikitable width="100%" |
||
!Problem |
!Problem |
||
Line 43: | Line 471: | ||
|Overloading operators <code>i++</code> or <code>++i</code><br/>See [http://www.parashift.com/c++-faq-lite/operator-overloading.html#faq-13.14] for more details. |
|Overloading operators <code>i++</code> or <code>++i</code><br/>See [http://www.parashift.com/c++-faq-lite/operator-overloading.html#faq-13.14] for more details. |
||
| |
| |
||
{{nb|1=<source lang="cpp"> |
|||
{{nb|<source lang="c"> |
|||
class Number { |
class Number { |
||
public: |
public: |
||
Line 57: | Line 484: | ||
|Reset <code>ostringstream</code> |
|Reset <code>ostringstream</code> |
||
| |
| |
||
{{nb|<source lang=" |
{{nb|1=<source lang="cpp"> |
||
ostringstream oss; |
ostringstream oss; |
||
oss << "Hello," << 123 << endl; |
oss << "Hello," << 123 << endl; |
||
Line 66: | Line 493: | ||
</source>}} |
</source>}} |
||
|} |
|} |
||
== Pits == |
|||
=== Persistent iomanip flags === |
|||
{{file|iostream}} is by far the sh*tiest IO library as easily demonstrated by the amount of code needed to simply print hexadecimal numbers, and still even get it right [https://stackoverflow.com/questions/5760252/how-can-i-print-0x0a-instead-of-0xa-using-cout] |
|||
<source lang="c++"> |
|||
# Print hexadecimal number |
|||
cout << "0x" << setfill('0') << setw(2) << hex << 10 << endl; // WRONG!!! |
|||
cout << "0x" << setfill('0') << setw(2) << right << hex << 10 << endl; // GOOD |
|||
cout << "0x" << setfill('0') << setw(2) << internal << hex << 10 << endl; // BETTER |
|||
</source> |
|||
When using <code>setw</code>, we '''must''' use either <code>left</code>, <code>right</code> or <code>internal</code> to make sure we don't inherit one of the previous setting. |
|||
=== Not using a by-reference auto type === |
|||
Say we have a <code>vector</code> of <code>vector</code>. If we want to clear them all, we need to make sure we use a <code>auto&</code>: |
|||
<source lang="c"> |
|||
vector<vector<int>> list_of_list; |
|||
// for(auto v: list_of_list) -- BAD! we would clear a temporary copy |
|||
for(auto& v: list_of_list) |
|||
{ |
|||
v.clear(); |
|||
} |
|||
</source> |
|||
=== Use off-bound indices in vector === |
|||
<code>vector</code> does NOT do range checking: |
|||
<source lang="c"> |
|||
vector<int> v; |
|||
v.resize(5); |
|||
v[5] = 10; // BAD will not be caught -- may sigfault or not |
|||
</source> |
|||
== Binary I/O == |
|||
See [http://courses.cs.vt.edu/~cs2604/fall02/binio.html] for reference: |
|||
<ul> |
|||
<li>Open a file. Binary file '''must''' be opened with mode '''ios::binary'''.</li> |
|||
<source lang="cpp"> |
|||
// Open a file for input |
|||
ifstream myFile ("data.bin", ios::in | ios::binary); |
|||
// Open a file for output |
|||
ofstream myFile; |
|||
... |
|||
myFile.open ("data2.bin", ios::out | ios::binary); |
|||
// Open a file for input and output |
|||
fstream myFile; |
|||
myFile.open ("data3.bin", ios::in | ios::out | ios::binary); |
|||
</source> |
|||
<li>Read from a file. Complex data must be casted to <code>(char*)</code>.</li> |
|||
<source lang="cpp"> |
|||
#include <fstream.h> |
|||
... |
|||
char buffer[100]; |
|||
ifstream myFile ("data.bin", ios::in | ios::binary); |
|||
myFile.read (buffer, 100); |
|||
if (!myFile) { |
|||
// An error occurred! |
|||
// myFile.gcount() returns the number of bytes read. |
|||
// calling myFile.clear() will reset the stream state |
|||
// so it is usable again. |
|||
} |
|||
... |
|||
if (!myFile.read (buffer, 100)) { |
|||
// Same effect as above |
|||
} |
|||
</source> |
|||
<li>Write to a file. Complex data must be casted to <code>(char*)</code>.</li> |
|||
<source lang="cpp"> |
|||
#include <fstream.h> |
|||
... |
|||
char buffer[100]; |
|||
ofstream myFile ("data.bin", ios::out | ios::binary); |
|||
myFile.write (buffer, 100); |
|||
</source> |
|||
</ul> |
|||
== Security Tips == |
== Security Tips == |
||
Line 84: | Line 594: | ||
generated. Two output formats are implemented: POSIX and GNU (extended). |
generated. Two output formats are implemented: POSIX and GNU (extended). |
||
== Miscellaneous == |
|||
== <iostream.h> or <iostream> == |
|||
=== <iostream.h> or <iostream> === |
|||
* <code><iostream></code> is the standard compliant library. <code><iostream.h></code> is deprecated since many many years. |
* <code><iostream></code> is the standard compliant library. <code><iostream.h></code> is deprecated since many many years. |
||
* <code><iostream></code> contains a set of templatized I/O classes which support both ''narrow'' and ''wide'' characters (by contrast, <code><iostream.h></code> classes are confined to ''char'' exclusively). |
* <code><iostream></code> contains a set of templatized I/O classes which support both ''narrow'' and ''wide'' characters (by contrast, <code><iostream.h></code> classes are confined to ''char'' exclusively). |
||
Line 90: | Line 601: | ||
* Finally, <code><iostream></code> components are declared in namespace <u><code>std</code></u> whereas <code><iostream.h></code> components are declared in the global scope. |
* Finally, <code><iostream></code> components are declared in namespace <u><code>std</code></u> whereas <code><iostream.h></code> components are declared in the global scope. |
||
Note that both libraries '''cannot''' be mixed in one program. |
Note that both libraries '''cannot''' be mixed in one program. |
||
== Data structures == |
|||
=== Tree Iterator === |
|||
* Using ''parent'' pointer [https://secweb.cs.odu.edu/~zeil/cs361/web/website/Lectures/treetraversal/page/treetraversal.html] |
|||
* Using ''threaded tree''. Threaded trees replaces the null ''right'' pointer with a pointer to next node. [https://secweb.cs.odu.edu/~zeil/cs361/web/website/Lectures/treetraversal/page/treetraversal.html] |
|||
: This requires a boolean flag to tell whether the right pointer is a child or thread. |
|||
== Libraries == |
|||
=== Math === |
|||
* [https://eigen.tuxfamily.org/index.php?title=Main_Page Eigen] |
|||
: Eigen is a C++ template library for linear algebra: matrices, vectors, numerical solvers, and related algorithms. |
|||
* [https://bitbucket.org/blaze-lib/blaze/src/master/ Blaze] |
|||
: Blaze is an open-source, high-performance C++ math library for dense and sparse arithmetic. |
Latest revision as of 15:39, 14 March 2024
References
See also C references and C / C++.
Links
- C++ language
- http://en.cppreference.com/ (can be freely downloaded, or installed as package cppreference-doc-en-html, view with DevHelp).
- www.cplusplus.com — C++ Reference
- Including C Language Library
- and ... IOStream Library
- Create a local copy with:
# Make a local copy of www.cplusplus.com - use option -P http://proxy:port if needed
sudo mkdir httrack
sudo chown www:www-data httrack/
cd httrack/
sudo su www -c "httrack http://www.cplusplus.com/ -W -O /var/www/httrack -I0 -n -d -%v \
'-www.cplusplus.com/forum/*' '-www.cplusplus.com/src/*' '-www.cplusplus.com/member/*' \
'-www.cplusplus.com/user/*' '-www.cplusplus.com/contact*' -P 127.0.0.1:8118"
- STL
- See cppreference.com and cplusplus.com above.
- SGI — Standard Template Library Programmer's Guide
- libstd++-x.x-doc package
sudo apt install libstd++-6-doc
man std::vector
- Miscellaneous
- manpage stl-manual (from SGI)
sudo apt-get install stl-manual
ln -s /usr/share/doc/stl-manual/html /var/www/sgi # Now the manual is available at http://localhost/sgi
Books
C++ Standards
C++11
- References
- https://blog.smartbear.com/development/the-biggest-changes-in-c11-and-why-you-should-care/
- https://en.wikipedia.org/wiki/C%2B%2B11
- http://www.stroustrup.com/C++11FAQ.html
- Range-based for loop
C++11 introduces range-based for loops:
std::vector<int> v = {0, 1, 2, 3, 4, 5};
const auto& cv = v;
int a[] = {0, 1, 2, 3, 4, 5};
for (const int& i : v) // access by const reference
for (auto i : v) // access by value, the type of i is int
for (auto&& i : v) // access by forwarding reference, the type of i is int&
for (auto&& i : cv) // access by f-d reference, the type of i is const int&
for (int n : {0, 1, 2, 3, 4, 5}) // the initializer may be a braced-init-list
for (int n : a) // the initializer may be an array
Use std::as_const(x)
to prevent copy-on-write:
struct cow_string { /* ... */ }; // a copy-on-write string
cow_string str = /* ... */;
// for(auto x : str) { /* ... */ } // may cause deep copy
for(auto x : std::as_const(str)) { /* ... */ }
This is not to be confused with the for_each
algorithm in STL.
- Lambda expressions
A lambda expression has the form: [capture](parameters)->return-type {body}
.
int main()
{
char s[]="Hello World!";
int Uppercase = 0; //modified by the lambda
for_each(s, s+sizeof(s), [&Uppercase] (char c) {
if (isupper(c))
Uppercase++;
});
cout<< Uppercase<<" uppercase letters in: "<< s<<endl;
}
- Automatic Type Deduction
auto
anddecltype
Use keyword auto
to infer the type of an object automatically:
auto x=0; //x has type int because 0 is int
auto c='a'; //char
auto d=0.5; //double
auto national_debt=14400000000000LL;//long long
The new operator decltype
takes an expression and returns its type:
const vector<int> vi;
typedef decltype (vi.begin()) CIT;
CIT another_const_iterator;
Note that the reference type of auto&&
depends on the the reference given (as per reference collapsing rule [1]) [2]:
A& & becomes A&
A& && becomes A&
A&& & becomes A&
A&& && becomes A&&
For short, auto&&
is an universal reference (like T&&
in templates) that just binds to anything [3].
- Uniform Initialization Syntax
C++ has at least four different initialization notations, some of which overlap.
Parenthesized initialization looks like this:
std::string s("hello");
int m=int(); //default initialization
You can also use the =
notation for the same purpose in certain cases:
std::string s="hello";
int x=5;
For POD aggregates, you use braces:
int arr[4]={0,1,2,3};
struct tm today={0};
Finally, constructors use member initializers:
struct S {
int x;
S(): x(0) {} };
C++11 cleans up this mess with a uniform brace notation:
class C
{
int a;
int b;
public:
C(int i, int j);
};
C c {0,0}; //C++11 only. Equivalent to: C c(0,0);
int* a = new int[3] { 1, 2, 0 }; //C++11 only
class X {
int a[4];
public:
X() : a{1,2,3,4} {} //C++11, member array initializer
};
In C++11 you can initialize containers intuitively:
// C++11 container initializer
vector<string> vs={ "first", "second", "third"};
map singers =
{ {"Lady Gaga", "+1 (212) 555-7890"},
{"Beyonce Knowles", "+1 (212) 555-0987"}};
Similarly, C++11 supports in-class initialization of data members:
class C
{
int a=7; //C++11 only
public:
C();
};
- Deleted and Defaulted Functions
Defaulted functions instruct the compiler to provide the default implementation for these functions:
struct A
{
A()=default; //C++11
virtual ~A()=default; //C++11
};
The opposite of a defaulted function is a deleted function. To disable copying, declare these two special member functions =delete:
struct NoCopy
{
NoCopy & operator =( const NoCopy & ) = delete;
NoCopy ( const NoCopy & ) = delete;
};
NoCopy a;
NoCopy b(a); //compilation error, copy ctor is deleted
- nullptr
nullptr
is strongly-typed:
void f(int); //#1
void f(char *);//#2
//C++03
f(0); //which f is called?
//C++11
f(nullptr) //unambiguous, calls #2
- Delegating Constructors
In C++11 a constructor may call another constructor of the same class:
class M //C++11 delegating constructors
{
int x, y;
char *p;
public:
M(int v) : x(v), y(0), p(new char [MAX]) {} //#1 target
M(): M(0) {cout<<"delegating ctor"<<endl;} //#2 delegating
};
- Rvalue References
Rvalue references can bind to rvalues, e.g. temporary objects and literals [4].
The primary reason for adding rvalue references is move semantics.
you can declare a move constructor and a move assignment operator like this:
class Movable
{
Movable (Movable&&); //move constructor
Movable&& operator=(Movable&&); //move assignment operator
};
std::move
is used to indicate that an object t may be "moved from", i.e. allowing the efficient transfer of resources from t to another object.
// Simple move constructor
A(A&& arg) : member(std::move(arg.member)) // the expression "arg.member" is lvalue
{}
// Simple move assignment operator
A& operator=(A&& other) {
member = std::move(other.member);
return *this;
}
Reference collapsing rule [5]:
typedef int& lref;
typedef int&& rref;
int n;
lref& r1 = n; // type of r1 is int&
lref&& r2 = n; // type of r2 is int&
rref& r3 = n; // type of r3 is int&
rref&& r4 = 1; // type of r4 is int&&
- More stuff
- C++11 Standard Library
- Threading Library
- New Smart Pointer Classes
- New C++ Algorithms
C++14
- References
- http://www.drdobbs.com/cpp/the-c14-standard-what-you-need-to-know/240169034
- https://en.wikipedia.org/wiki/C%2B%2B14
- https://www.quora.com/What-are-the-key-new-features-in-the-C++-14-standard
- Return type deduction
auto
can be used as function return type. Most useful when combined with templates, or to avoid cascade of API changes if changing some object internal type.
auto getvalue()
{
return 1.4;
}
- Generic lambdas
These are lambdas using auto
as parameter type:
// Here we make in fact a named-lambda
auto adder = [](auto op1, auto op2){ return op1 + op2; };
This is the loose equivalent of creating a template function.
- Initialized Lambda Captures
Now lambda parameter can be initialized:
auto y = [&r = x, x = x+1]()->int {...}
This allows for the move semantic in lambdas:
#include <memory>
#include <iostream>
int main()
{
std::unique_ptr<int> p(new int);
int x = 5;
*p = 11;
auto y = [p=std::move(p)]() { std::cout << "inside: " << *p << "\n";};
y();
std::cout << "outside: " << *p << "\n";
return 0;
}
- The
deprecated
attributes
[[deprecated("Consider using something other than cranky")]]
int cranky()
{
return 0;
}
Handling is compiler specific.
- Binary Literals and Digit Separators
Now we can use 0b
to construct binary literals (like 0x
for hex).
int val = 0b11110000;
Use '
to separate digit group (will not change the value):
int mask = 0b1000'0001'1000'0000;
float salary = 300'000.00;
- Miscellaneous
- Variable templates
make_unique
auto up = make_unique<LongTypeName>(args) # Better than calling new without disclaimer
C++17
- C++17 - What's New in the Core Language?
- https://github.com/tvaneerd/cpp17_in_TTs/blob/master/ALL_IN_ONE.md
- Description of C++17 features, in 100 source code examples.
C++0x (old stuff)
- C++0x - the next ISO C++ standard (Bjarne Stroustrup)
- C++0x support in GCC
- The Biggest Changes in C++11 (and Why You Should Care)
- auto_ptr deprecated
- unique_ptr and shared_ptr
- Using unique_ptr, Part I
Basically, unique_ptr permits move from rvalues with copy syntax using a move constructor (which binds to rvalues), while blocking the copy from lvalues by making the copy constructor (which binds to lvalues) private:
template <class T>
class unique_ptr
{
public:
unique_ptr(unique_ptr&& u); // rvalues bind here
private:
unique_ptr(const unique_ptr&); // lvalues bind here
};
- http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=239 The shared_ptr Class]
- rvalue references (and move semantics)
Benchmark
Between compilers
- g++
- EKOPath4, a recently open-sourced compiler with much better performance than gcc/g++.
- Intel compiler
- pathCC, PathScale compiler
Between languages
- C++ reported to be the fastest language, even faster than C and java. See The Computer Language Benchmarks Game
- C++ the Clear Winner In Google's Language Performance Tests
Nested Classes
See Nested classes on ibm.com.
Virtual destructors
Rule of thumb: make your destructor virtual if your class has any virtual functions.
Virtual destructors are needed when a derived class is explicitly deleted via delete
, but using a reference/pointer to a base class.
Patterns
Resource Allocation Is Initialization (RAII)
Reference:
- Resource Acquisition Is Initialization
- Bjarne Stroustrup's explanation about absence of
finally
block
From Kevin on stackoverflow.com: The idea is that an object's destructor is responsible for freeing resources. When the object has automatic storage duration, the object's destructor will be called when the block in which it was created exits — even when that block is exited in the presence of an exception.
Concurrency
Tips
Scoped enums
Use scoped enums to specify the underlying (storage) type for enums (available since c++11, ie. gcc/clang option -std=c++11
):
typedef enum : unsigned char { zero, one, two } enum8_t;
typedef enum : unsigned short { zero16, one16, two16 } enum16_t;
assert (sizeof(enum8_t) == 1);
assert (sizeof(enum16_t) == 2);
Finally blocks
From stackoverflow.com:
int * array = new int[10000000];
try {
// Some code that can throw exceptions
// ...
throw std::exception();
// ...
} catch (...) {
// The finally-block (if an exception is thrown)
delete[] array;
// re-throw the exception.
throw;
}
// The finally-block (if no exception was thrown)
delete[] array;
Note that the finally block may throw an exception, hence discarding the original exception.
To avoid the double delete
:
std::exception_ptr e;
try {
/*try block*/
}
catch (...) {
/*finally block*/
e = std::current_exception();
}
if (e) { // e evaluates to 'false' if no exception!
std::rethrow_exception(e);
}
Miscellaneous
Problem | Solution |
---|---|
Overloading operators i++ or ++i See [6] for more details. |
class Number {
public:
// prefix ++ - Must return (*this)
Number& operator++ ();
// postfix ++ - Must never return (*this) by reference
Number operator++ (int); // ... OR ....
void operator++ (int);
};
|
Reset ostringstream
|
ostringstream oss;
oss << "Hello," << 123 << endl;
string s = oss.str();
oss.str(""); // oss empty now - we can reuse it
oss << "World!" << 456 << endl;
|
Pits
Persistent iomanip flags
iostream is by far the sh*tiest IO library as easily demonstrated by the amount of code needed to simply print hexadecimal numbers, and still even get it right [7]
# Print hexadecimal number
cout << "0x" << setfill('0') << setw(2) << hex << 10 << endl; // WRONG!!!
cout << "0x" << setfill('0') << setw(2) << right << hex << 10 << endl; // GOOD
cout << "0x" << setfill('0') << setw(2) << internal << hex << 10 << endl; // BETTER
When using setw
, we must use either left
, right
or internal
to make sure we don't inherit one of the previous setting.
Not using a by-reference auto type
Say we have a vector
of vector
. If we want to clear them all, we need to make sure we use a auto&
:
vector<vector<int>> list_of_list;
// for(auto v: list_of_list) -- BAD! we would clear a temporary copy
for(auto& v: list_of_list)
{
v.clear();
}
Use off-bound indices in vector
vector
does NOT do range checking:
vector<int> v;
v.resize(5);
v[5] = 10; // BAD will not be caught -- may sigfault or not
Binary I/O
See [8] for reference:
- Open a file. Binary file must be opened with mode ios::binary.
- Read from a file. Complex data must be casted to
(char*)
. - Write to a file. Complex data must be casted to
(char*)
.
// Open a file for input
ifstream myFile ("data.bin", ios::in | ios::binary);
// Open a file for output
ofstream myFile;
...
myFile.open ("data2.bin", ios::out | ios::binary);
// Open a file for input and output
fstream myFile;
myFile.open ("data3.bin", ios::in | ios::out | ios::binary);
#include <fstream.h>
...
char buffer[100];
ifstream myFile ("data.bin", ios::in | ios::binary);
myFile.read (buffer, 100);
if (!myFile) {
// An error occurred!
// myFile.gcount() returns the number of bytes read.
// calling myFile.clear() will reset the stream state
// so it is usable again.
}
...
if (!myFile.read (buffer, 100)) {
// Same effect as above
}
#include <fstream.h>
...
char buffer[100];
ofstream myFile ("data.bin", ios::out | ios::binary);
myFile.write (buffer, 100);
Security Tips
Problem | Solution |
---|---|
Use mlock() to prevent a section of memory from swapping to disk(source: "Building Secure Software," John Viega & Gary McGraw) |
Tools
GNU cflow
GNU cflow analyzes a collection of C source files and prints a graph, charting control flow within the program.
GNU cflow is able to produce both direct and inverted flowgraphs for C sources. Optionally a cross-reference listing can be generated. Two output formats are implemented: POSIX and GNU (extended).
Miscellaneous
<iostream.h> or <iostream>
<iostream>
is the standard compliant library.<iostream.h>
is deprecated since many many years.<iostream>
contains a set of templatized I/O classes which support both narrow and wide characters (by contrast,<iostream.h>
classes are confined to char exclusively).- Third, the C++ standard specification of iostream's interface was changed in many subtle aspects. Consequently, the interfaces and implementation of
<iostream>
differ from<iostream.h>
. - Finally,
<iostream>
components are declared in namespacestd
whereas<iostream.h>
components are declared in the global scope.
Note that both libraries cannot be mixed in one program.
Data structures
Tree Iterator
- Using parent pointer [9]
- Using threaded tree. Threaded trees replaces the null right pointer with a pointer to next node. [10]
- This requires a boolean flag to tell whether the right pointer is a child or thread.
Libraries
Math
- Eigen is a C++ template library for linear algebra: matrices, vectors, numerical solvers, and related algorithms.
- Blaze is an open-source, high-performance C++ math library for dense and sparse arithmetic.