Skip to content

Instantly share code, notes, and snippets.

@BimManager
Last active January 30, 2023 23:05
Show Gist options
  • Select an option

  • Save BimManager/d65caed9d77f868088bb3a407877baba to your computer and use it in GitHub Desktop.

Select an option

Save BimManager/d65caed9d77f868088bb3a407877baba to your computer and use it in GitHub Desktop.
cpp
#include <stdio.h>
/*
** prototypes
*/
void test1();
void test2();
void test3();
/*
** an array of three function pointers
*/
void (*functptr[])() = { &test1, &test2, &test3 } ;
void main() {
(*functptr[0])(); /* Call first function */
(*functptr[1])(); /* Call second function */
(*functptr[2])(); /* Call third function */
}
void test1() {
printf("hello 1\n");
}
void test2() {
printf("hello 2\n");
}
void test3() {
printf("hello 3\n");
}
FUNCTIONS
// Function prototypes
long* foo(int, char&, char*, char*&); // returns a pointer to long
// ^ ^ ^ ^
// pass byValue byReference ByPointer PointerByReference
class Baz {
public:
Baz(); // constructor
~Baz(); // destructor
// member functions => accessor and mutator functions
void foo( ) const; // accessor function => (a read-only function)
void bar( ); // mutator function
private:
...
}
// The syntax for defining an accessor function
<return-value> <class>::<member-function>(<args>) const { }
void Baz::foo() const { /* definition */ }
// Const functions can be called by any objects
// Non-const functions can only be called by non-const objects
// When const functions return references or pointers to members of the class,
// they must also be const.
const int* Foo::Baz() const { /* definition */ }
extern int i; // declared inside a function which needs to access the global
// variable i declared below the function's declaration
struct book {
int i;
mutable char*; // even if an object of type book is declared as const
// this field still can be modified
}
inline void print(const char*); // inline functions
(11.5) An ordinary member function declaration specifies three logical distinct thigns:
[1] The function can access the private part of a class declaration
[2] The function is in the scope of the class
[3] The function must be invoked on an object (has a this pointer)
By declaring a function static, it is given the first two properties. By declaring a function friend, it will get only the first property.
CLASSES AND STRUCTS
By default, all members of a class are private, whereas all members of a struct are public.
ref class
A value class is a ValueType - that means, whenever you assign it to another variable of the same type, the whole object gets copied into the other variable, leaving you with two separate copies. Examples of this are basic numeric data types like int, bool or double. ValueTypes are sealed, which means you cannot derive from them.
A ref class is a reference type - if you assign it to another variable of the same type, you copy only a reference. So the two variables basically "point" to the same data.
So the main difference between value class and ref class are the copying semantics. Both can contain Methods, fields properties and so on. Also, you cannot derive from a value class.
The difference between using the class and struct keywords in this context is the default visibility of members. It is private for ref/value class and public for ref/value struct.
A common misconception is that value/ref specify the storage location (value=stack, ref=heap). The storage location of each object, whether ValueType or reference type, is an implementation detail noone should rely on or make assumptions about and it is entirely at the runtime's discretion which storage location is appropriate in any given context.
Classes containing a pointer data member (10.4.4.1)
#define BUFFER 1024
typedef unsigned long DWORD;
using SuperInt = int;
class Foo {
public:
Foo(); // constructor
~Foo(); // destructor
Foo(const Foo&); // copy constructor
Foo& operator=(const Foo&); // assingment operator
private:
DWORD* pdwRg;
int size:10; // 10 bits = 1024
};
// constructor definition
Foo::Foo()
:size(0) {
pdwRg = new DWORD[BUFFER];
}
// destructor definition
Foo::~Foo() {
delete[] pdwRg;
pdwRg = NULL;
}
// copy constructor definition
Foo::Foo(const Foo& src)
:size(src.size) {
pdwRg = new DWORD[BUFFER];
for(int i = 0; i < src.size; ++i)
*(pdwRg + i) = *(other.pdwRg + i);
}
// assignment operator
Foo& Foo::operator=(const Foo& src) {
if(this != &src) { // beware of self-assignment
size = src.size;
delete[] pdwRg; // the object assigned to has already been initialised,
// therefore, its pointer has to be deleted first
pdwRg = new DWORD[BUFFER];
for(int i = 0; i < src.size; ++i)
*(pdwRg + i) = *(src.pdwRg + i);
}
return *this; // return this object (pointer this)
}
// Strategies for an assignment operator
// 1. protect against self-assignment
// 2. delete old elements
// 3. initialise
// 4. copy in new elements (every non-static member must be copied)
The copy constructor is called when an object is
- passed by value to a function
- returned by value from a function
- declared with the aid of an existing object of the same class
<h3>POINTERS TO FUNCTIONS</h3>
void baz(int);
void (*pfnbaz)(int) = &baz; // or =baz;
// POINTERS TO MEMBERS
struct _Bar { int m; } SBar, *pSBar;
int _Bar::*pm = _Sbar::m; // a pointer to a data member of class C
SBar.m = 10;
std::cout << SBar.*pm; // prints out 10
// POINTERS TO MEMBER FUNCTIONS
struct _Baz { void foo(int); } SBaz, *pSBaz;
void (_Baz::*pfnfoo)(int) = &_Baz::foo;
// Define a pointer to
// a specific member function
void (Foo::* pPrint)() = &Foo::Print();
// Create an instance of the class
Foo* pFoo = new Foo();
// Call the function by dint of
// the pointer
(pFoo->*pPrint)();
delete pFoo;
STATIC MODIFIER
Applied to a global variable, the variable's global nature is restricted to the source file in which it is declared.
Applied to a variable within a function, the variable will not go out of scope or be deleted when the function exits. (p 410)
Applied to a variable with a class, only one copy of this variable is created, shared by all memebers of the class.
Applied to a method within a class, the method is accessible without the need to instantiate the class.
In C, if a function is declared static, then it cannot be accessed outside of its source file.
INHERITANCE AND COMPOSITION
Pure virtual function => virtual void Func ( ) = 0;
If a class contains at least one pure virtual function, then this class is called an abstract class.
EXCEPTION HANDLING
TRY-CATCH
void foo() throw(); // does not throw any exception
void bar() throw(...); // throws an exception
void baz() throw(int); // throws an exception of type int
// in c++, the following is preferred
void foo() noexcept; // throws an exception equivalent to noexcept(true)
void bar() noexcept(true/false); // throws an exception depending on true/false
// nested try-catch blocks
try {
try {
throw 10;
}
catch(int) {
std::cout<<"Caught int exception\n";
throw; // forward the exception to the parent try-catch block
}
catch(...) {
std::cout<<"An error occurred\n";
}
}
If a destructor throws an exception during stack unwinding the whole program will exit.
During an exception, program execution moves to that exception’s exception handler, destroying all automatic variables between the throw and catch. The process is called stack unwinding.
It is not considered good practice to throw exception in an object destructor.
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <tchar.h>
#include <exception>
#include <vector>
typedef struct {
int id;
int locationId;
int level;
TCHAR* description;
TCHAR* reason;
} ERRORINFO, *PERRORINFO;
class myexception: public std::exception {
TCHAR* m_msg;
std::vector<PERRORINFO> m_errorlist;
public:
myexception(TCHAR* msg)
:m_msg(msg) {}
virtual ~myexception() noexcept {
m_errorlist.clear();
}
virtual char const* what() const { // an accessor function
return m_msg;
}
void adderror(PERRORINFO info) throw(std::bad_alloc) {
try {
m_errorlist.push_back(info);
}
catch(...) {
std::cout<<"Bad alloc in adderror function\n";
}
}
auto begin() { return m_errorlist.begin(); }
auto end() { return m_errorlist.end(); }
};
int _tmain(int argc, TCHAR** argv, TCHAR** env) {
try {
try {
try {
myexception myex(_T("myexception object thrown"));
_tprintf(_T("sizeof(myexception) = %d\n"), sizeof(myexception));
_tprintf(_T("sizeof(ERRORINFO) = %d\n"), sizeof(ERRORINFO));
throw myex;
}
catch(myexception& ex) {
ERRORINFO errinfo;
errinfo.id = 1;
errinfo.locationId = 1;
errinfo.level = 1;
errinfo.description = _T("First level exception thrown.");
ex.adderror(&errinfo);
throw ex;
}
}
catch(myexception& ex) {
ERRORINFO errinfo;
errinfo.id = 2;
errinfo.locationId = 2;
errinfo.level = 2;
errinfo.description = _T("Second level exception thrown.");
ex.adderror(&errinfo);
throw ex;
}
}
catch(myexception& ex) {
// print out erroinfo structs
for(auto it = ex.begin(); it != ex.end(); ++it) {
ERRORINFO einfo = **it;
std::cout<<einfo.id<<" "<<einfo.locationId<<" "<<einfo.level<<" "<<einfo.description<<" "<<'\n';
}
}
return 0;
}
errno.h
#include <errno.h>
#include <string.h>
/* ... */
if(read(fd, buf, 1)==-1) {
printf("Oh dear, something went wrong with read()! %s\n", strerror(errno));
}
RAII (RESOURCE ACQUISITION IS INITIALISATION)
> C++ guarantess that the destructors of objects allocated on the stack will be called even if an exception is thrown.
There are three parts to an RAII class:
- The resource is relinquished in the destructor.
- Instances of the class are stack allocated.
- The resource is acquired in the constructor.
C++ BIT FIELDS
cppreference
Classes and structures can contain members that occupy less storage than an integral type.
These members are specified as bit fields.
// Syntax
declarator : constant-expression
// the member must be an integral type (including enumerated types)
// Anonymous fit fields (with no identifier) can be used for padding
// bit_fields.cpp
// compile with: /LD
typedef unsigned short WORD;
typedef unsigned long DWORD;
typedef unsigned __int64 QWORD;
struct Date {
WORD nWeekDay : 3; // 0..7 (3 bits)
WORD nMonth : 4; // 0..15 (4 bits)
WORD nMonthDay : 5; // 0..31 (5 bits)
WORD : 0; // force alignment to next boundary
WORD nYear : 8; // 0..127 (8 bits)
};
TEMPLATES
// foo.h
template<class T>
class Foo {
T m_Value;
public:
Foo();
T GetValue() const;
};
// foo.cpp
#include "foo.h"
TRAITS CLASSES
// Generic template class
template<typename T>
struct is_void {
static const bool value = false; // enum { value = false };
};
// Full specialisation for void
struct is_void<void> {
static const bool value = true;
};
// General template class
template<typename T>
struct is_pointer {
static const bool value = false;
};
// Partial specialisation for all pointer types
template<typename T>
struct is_pointer<T*> { // extra <...> after the class name
static const bool value = true;
};
// General template class
template<typename T>
struct remove_bounds {
typedef T type;
};
// Partial specialisation
template <typename T, std::size_t N>
struct remove_bounds<T[N]> {
typedef T type;
};
Functors
// functors.h
#ifndef FUNCTORS_H_
#define FUNCTORS_H_
namespace Lesson {
// Abstract base class
class BinaryFunction {
public:
BinaryFunction() { };
virtual double operator() (double, double) = 0;
};
// Add two doubles
class Add : public BinaryFunction {
public:
Add() { };
virtual inline double operator() (double a, double b) { return a+b; }
};
// Multiply two doubles
class Multiply : public BinaryFunction {
public:
Multiply() { };
virtual inline double operator() (double a, double b) { return a*b; }
};
}
#endif // FUNCTORS_H_
// main.cpp
#include <iostream>
#include <tchar.h>
#include "functors.h"
int _tmain(int argc, TCHAR** argv, TCHAR** env) {
try {
double a = 5.0;
double b = 10.0;
double res;
Lesson::BinaryFunction* pAdd = new Lesson::Add();
res = (*pAdd)(a,b);
std::cout<<"result = "<<res<<'\n';
Lesson::BinaryFunction* pMultiply = new Lesson::Multiply();
res = (*pMultiply)(a,b);
std::cout<<"result = "<<res<<'\n';
delete pAdd;
pAdd = NULL;
delete pMultiply;
pMultiply = NULL;
} catch(...) {
return 1;
}
return 0;
}
STDAFX.H
stdafx.h is a precompiled header, in which afx stands for application framework extensions, which includes headers that are frequently used but hardly ever change.
Simply put, all huge headers are to be #included in stdafx.h header, in the appropriate order. Afterwards, stdafx.h shall be included in every cpp file at the very top before any other headers - for Visual C++ will not compile anything before the #include “stdafx.h” in the source file, unless /Yu”stdafx.h” is unchecked (by default).
A quick guide to using precompiled headers
How to use precompiled files on the command line
1. Create an stdafx.h, add an include guard and include all necessary headers.
// stdafx.h
// It contains headers that are used frequently but hardly ever change.
#ifndef STDAFX_H
#define STDAFX_H
#pragma comment(lib, "kernel32")
#pragma comment(lib, "user32")
#pragma comment(lib, "gdi32")
#include <windows.h>
#endif // STDAFX_H
2. Create an stdafx.cpp and `#include` `"``stdafx.h``"` ``.
3. cl /c /Ycstdafx.h stdafx.cpp
4. cl /Yustdafx.h prog.cpp /link stdafx.obj
Linker Tools Error LNK2011
CONTAINERS
container<T>::iterator
container<T>::const_iterator
container<T>::size_type
map<string, int> counters;
++counters[s]; // when a key is seen for the first time
// the map automatically creates a new element with that key.
ALGORITHMS
std::copy(container.begin(), container.end(), back_inserter(container2));
ITERATORS
Iterator adaptors
back_inserter(container);
front_inserter(container);
inserter(assoc_container);
TYPES OF BINDINGS
Compile-time binding
(static binding / early binding)
Run-time binding (achieved via virtual functions)
(dynamic binding / late binding)
if a base class contains virtual functions, the destructor
of the base class must be made virtual
<=PInvoke Basics=>
Compiling a native C/C++ program on the command line
#include <stdio.h>
#include <wchar.h>
extern "C" {
__declspec(dllexport)
void print_helo(const wchar_t* u) {
wprintf(L"helo: %s\n", u);
}
} // extern "C"
To output .dll
cl.exe /D_USRDLL /D_WINDLL name.cpp /MT /link /DLL /OUT:name.dll
On the command line use: cl.exe /LD <files-to-compile>
or, if you prefer the more verbose & explicit version:
cl.exe /D_USRDLL /D_WINDLL <files-to-compile> <files-to-link> /link /DLL /OUT:<desired-dll-name>.dll
CALLING WinMain FROM C#
using System.Runtime.InteropServices;
class Program {
// use DLL Export View to get hold of the exported function name
// that shall be used as an entry point
[DllImport(@"...\.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = " ", ExactSpelling = true)]
static extern void Run(IntPtr hInstance, int iCmdLine);
[DllImport("kernel32.dll", CallingConvention = CallingConvention.StdCall)]
static extern IntPtr GetModuleHandle([MarshalAs(UnmanagedType.LPTStr)] string lpModuleName);
static void Main(string[] args) {
// an alternative way for invoking WinMain
System.Diagnostics.Process.Start(@"...\.dll");
unsafe {
IntPtr hModule = GetModuleHandle(null);
IntPtr hInstance = Marshal.GetHINSTANCE(typeof(Program).Module);
// hModule == hInstance
int iCmdLine = 5;
Run(hInstance, iCmdLine);
}
Console.ReadKey();
}
}
// pinvoke.h
#include <windows.h>
#ifndef MY_PINVOKE_H
#define MY_PINVOKE_H
#ifdef __cplusplus
extern "C" {
#endif
__declspec(dllexport) void __stdcall Run(HINSTANCE, int);
//__declspec(dllexport)
LRESULT WINAPI WinProc(HWND, UINT, WPARAM, LPARAM);
//__declspec(dllexport)
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPTSTR, int);
#ifdef __cplusplus
}
#endif
#endif // MY_PINVOKE_H
// pinvoke.cpp
#include "pinvoke.h"
__declspec(dllexport)
void __stdcall Run(HINSTANCE hInstance, int iCmdLine) {
WinMain(hInstance, NULL, NULL, iCmdLine);
}
![](https://d2mxuefqeaa7sj.cloudfront.net/s_1D1BEF00B6FB6EDD05D62A7E116D09EBF1029349CA9F5D0976672B68BF2456FB_1525431906638_image.png)
1. Use the MarshalAsAttribute.
Since the 2 parameters of the splitTiff() API are wide character strings :
__declspec(dllexport) void _stdcall splitTiff(LPCWSTR sourceFile, LPCWSTRoutputDirectoryPlusPrefixWithPercentD);
The corresponding parameters for the C# declaration should be marked with the MarshalAsAttribute with the UnmanagedType.LPWStr argument :
[DllImport("C:\\Tiff-DLLs\\TiffSplitter.dll")]
public static extern void splitTiff([MarshalAs(UnmanagedType.LPWStr)]string sourceFile,[MarshalAs(UnmanagedType.LPWStr)]string dir);
1.2 I suggest that you create a trivial implementation for splitTiff() to make sure that the parameters are indeed correct, e.g. :
__declspec(dllexport) void _stdcall splitTiff(LPCWSTR sourceFile, LPCWSTR outputDirectoryPlusPrefixWithPercentD)
{
// Just perform logging of sourceFile and outputDirectoryPlusPrefixWithPercentD
// to ensure that they are correct.
}
2. Entry Point Name for splitTiff().
2.1 Are you able to call the splitTiff() from the C# code ?
2.2 Note that if you do not supply the EntryPoint= argument for the DllImportAttribute, the API is assumed to be stdcall and the name is expected to be either splitTiff (if a .DEF file is used) or _splitTiff@8 (by default, due to stdcall convention).
2.3 As mentioned by davewilk, if you have not used the extern "C" declaration for splitTiff(), something like :
extern "C" __declspec(dllexport) void _stdcall splitTiff(LPCWSTR sourceFile, LPCWSTRoutputDirectoryPlusPrefixWithPercentD);
then the API is taken to be a C++ function and so name mangling will be applied. The name of the API will be set to something like the following : ?splitTiff@@YGXPB_W0@Z.
2.4 If this is the case, you would have to use the EntryPoint argument for the DllImportAttribute as follows :
[DllImport("C:\\Tiff-DLLs\\TiffSplitter.dll", EntryPoint="?splitTiff@@YGXPB_W0@Z")]
public static extern void splitTiff([MarshalAs(UnmanagedType.LPWStr)]string sourceFile, [MarshalAs(UnmanagedType.LPWStr)]string dir);
3. About DllMain().
>> By the way, am I SUPPOSED to have a Main in a DLL created for pinvoke?
I assume that you are talking about DllMain() and not WinMain(). No DllMain() is not strictly required in a DLL.
<=Helper Functions=>
// implementing is and as C# keywords
interface class I {
public:
void F();
};
ref struct C : public I {
virtual void F( void ) { }
};
template < class T, class U >
Boolean isinst(U u) {
return dynamic_cast< T >(u) != nullptr;
};
int main() {
C ^ c = gcnew C();
I ^ i = safe_cast< I ^ >(c); // is (maps to castclass in IL)
I ^ ii = dynamic_cast< I ^ >(c); // as (maps to isinst in IL)
// simulate 'as':
Object ^ o = "f";
if ( isinst< String ^ >(o) )
Console::WriteLine("o is a string");
}
// C# is => return true/false
if (obj is Person) {
// Do something if obj is a Person.
}
// C# as => return null/cast
Base b = d as Base;
if (b != null)
Console.WriteLine(b.ToString());
<=POINTERS & STRINGS=>
INTERIOR POINTERS
An interior pointer is a pointer to a managed object or a member of a managed object that is updated automatically to accommodate for garbage collection cycles that may result in the pointed-to object being relocated on the CLR heap. Furthermore, it exhibits pointer semantics as such pointer arithmetic.
- A native pointer gets converted implicitly to a interior pointer (The reverse is not allowed.)
- Can point to a reference handle
- Can point to inside a reference type (a member of a managed type)
- Can pointer to a value type
- Can point to a boxed type handle
- Can point to an element of a managed array
- CANNOT POINT TO A MANAGED OBJECT ITSELF
// cli::interior_ptr<cv_qualifier type> var = &initializer;
// const or volatile qualifiers
// initializer - A member of a reference type, element of a managed array,
// or any other ob ject that you can assign to a native pointer.
// passed by reference as an interior pointer
void Randomise(interior_ptr<int> ipInt) {
*ipInt = rand();
}
// passed by reference using a tracking reference
void Randomise(System::Int^& rhInt) {
rhInt = rand();
}
// Usage of an interior pointer in pointer arithmetic
#include <vcclr.h>
int _tmain(int argc, TCHAR** argv, TCHAR** env) {
try {
System::String^ hMsg = _T("Hello, world!");
System::Console::WriteLine(hMsg);
interior_ptr<System::Char> ipMsg =
const_cast<interior_ptr<System::Char>>(PtrToStringChars(hMsg));
while((*ipMsg++)++) // encript the string
;
System::Console::WriteLine(hMsg);
} catch(...) {
return 1;
}
return 0;
}
PINNING POINTERS
A pinning pointer pins a CLI object on the CLR heap
- To pass a pointer to a CLI object to a native function
- It is legal to convert pin pointers to native pointers.
- The duration of pinning is the lifetime pf the pinning pointer.
- To unpin, assign the pin pointer nullptr
// pin_ptr<type> var = [address];
System::String^ hmStr = "Preprocessor->Linker->Compiler->Loader->Execution";
pin_ptr<WCHAR> pWSTR =
const_cast<interior_ptr<WCHAR>>(PtrToStringChars(hmStr));
// Now this pointer may be passed to native functions taking wchar_t as an argument
STRING CONVERTION
//compiler option: cl /clr
#include <atlstr.h>
#include <stdio.h>
#using <mscorlib.dll>
using namespace System;
using namespace System::Runtime::InteropServices;
#if _MSC_VER > 1499 // Visual C++ 2008 only
#include <msclr/marshal.h>
using namespace msclr::interop;
#endif
int _tmain(void)
{
System::String ^ str = "Hello world\n";
//method 1*
pin_ptr<const wchar_t> pnpwszStr = &(str->ToCharArray()[0]);
wprintf(pnpwszStr);
//method 1
pin_ptr<const wchar_t> str1 = PtrToStringChars(str);
wprintf(str1);
//method 2
char* str2 = (char*)Marshal::StringToHGlobalAnsi(str).ToPointer();
printf(str2);
Marshal::FreeHGlobal((IntPtr)str2);
//method 3
CString str3(str);
wprintf(str3);
//method 4
#if _MSC_VER > 1499 // Visual C++ 2008 only
marshal_context ^ context = gcnew marshal_context();
const char* str4 = context->marshal_as<const char*>(str);
puts(str4);
delete context;
#endif
return 0;
}
SYSTEM::STRING^ to wchar_t* or char*
// convert_string_to_wchar.cpp
// compile with: /clr
#include < stdio.h >
#include < stdlib.h >
#include < vcclr.h >
using namespace System;
int main() {
String ^str = "Hello";
// Pin memory so GC can't move it while native function is called
pin_ptr<const wchar_t> wch = PtrToStringChars(str);
printf_s("%S\n", wch);
// Conversion to char* :
// Can just convert wchar_t* to char* using one of the
// conversion functions such as:
// WideCharToMultiByte()
// wcstombs_s()
// ... etc
size_t convertedChars = 0;
size_t sizeInBytes = ((str->Length + 1) * 2);
errno_t err = 0;
char *ch = (char *)malloc(sizeInBytes);
err = wcstombs_s(&convertedChars,
ch, sizeInBytes,
wch, sizeInBytes);
if (err != 0)
printf_s("wcstombs_s failed!\n");
printf_s("%s\n", ch);
}
<=Set up C++ for developing Revit add-ins=>
1. Platform: Active(x64)
2. Configuration Type: Dynamic Library (.dll)
3. Common Language Runtime Support (/clr)
4. .Net Target Framework Version v4.6.1
5. Add References (Set 'Copy Local' to False)
6. Create "stdafx.h”
7. Add macros
// Copyright 2021 kkozlov
#include <iostream>
// to make a custom type hashable and storable in maps and sets
struct LFUEntry {
int key;
int value;
int useCount;
int lastUse;
LFUEntry(int key, int value, int useCount, int lastUse) {
this->key = key;
this->value = value;
this->useCount = useCount;
this->lastUse = lastUse;
}
bool operator==(LFUEntry const& other) const {
return this->key == other.key;
}
struct HashFunction {
size_t operator()(LFUEntry const& entry) const {
return hash<int>()(entry.key);
}
};
};
<body>
<h2>C++ Idioms</h2>
<h3>Reading a File</h3>
<pre><code>
static int ReadFile(char const *filename) {
std::string line;
std::ifstream ifs(filename);
if (ifs.is_open(), std::ios::binary) {
while (std::getline(ifs, line))
std::cout << line;
ifs.close();
return 0;
} else {
std::cerr << "Unable to open file " << filename << std::endl;
return 1;
}
}
</code></pre>
</body>
int const N_CARS 42
class Car {
public:
Car(int no) : no_(no) {
}
private:
int no_;
};
int main() {
int i;
void *rawMemory = operator new[](N_CARS * sizeof(Car));
Car *pCars = static_cast<Car *>(rawMemory);
i = -1;
while (++i < N_CARS) {
new(&pCars[i]) Car(i);
// new(Cars + i) Car(i);
}
i = -1;
while (++i < N_CARS) {
ptr[i].~Car();
}
operator delete[](rawMemory);
return 0;
}
/*
** g++ --std=c++11 -pthread
*/
#include <iostream>
#include <thread>
static void entry_point(int) {
// do some work here
}
class background_task {
public:
void operator()(void) {
}
};
static void pass_by_ref(int const&) {
}
static void pass_by_pointer(int *value) {
*value = 42;
}
/*
** local objects in a function are destroyed
** in reverse order of consturction
*/
int main(void) {
std::thread t0(entry_point, 42); // works with any callable type (functions, lambdas, function objects)
// it is imperative to decide explicitely whether to wait (t.join()) for the thread
// or leave it to run on its own (t.detach())
// if it is not descided before the std::thread object is destroyed,
// then the program terminates (the std::thread desctructor calls std::terminate())
if (t0.joinable()) t0.join(); // makes the calling thread (main) to wait for thread t
// t.detach() detached thread are called daemon threads
//std::thread t1(background_task()); // c++'s most vexing parse
// defines a function t2
// that takes as a parameter a pointer to a function
// taking no parameter and returning background_task
// and returns a std::thread object
std::thread t2((background_task()));
if (t2.joinable()) t2.detach();
std::thread t3{background_task()};
if (t3.joinable()) t3.detach();
// use the RAII idiom
// by default the constructor of std::thread copies every parameter
// to pass a parameter by reference, std::ref is to be used
int num = 42;
std::thread t4(pass_by_ref, std::ref(num));
if (t4.joinable()) t4.join();
std::cout << num << std::endl;
num = 1;
std::thread t5(pass_by_pointer, &num);
if (t5.joinable()) t5.join();
std::cout << num << std::endl;
return 0;
}
<body>
<h2>Pointer declarations</h2>
<h3>Pointers to objects</h3>
<pre><code>
int n;
int *n_p;
n = 7;
n_p = &n;
std::cout << *n_p;
</code></pre>
<h3>Pointers to void</h3>
<h3>Pointers to functions</h3>
<pre><code>
typedef void (*PFN)(void);
PF edit_ops[] = {
&cut, &past, &copy, &search
};
(*edit_ops[i])();
</code></pre>
<h3>Pointers to members</h3>
<h3>Pointers to data members</h3>
<h3>Pointers to member functions</h3>
<pre><code>
struct Foo {
void f(int n) { std::cout << n << std::endl; }
};
int main(void) {
void Foo::*pf(int) = &Foo::f;
(*pf)->
</code></pre>
<h3>A reference pointer</h3>
<pre><code>
void pointerParameters(int* &p, int *q);
</code></pre>
</body>
std::stringstream buffer;
std::streambuf *old = std::cout.rdbuf(buffer.rdbuf());
std::cout << "Bla" << std::endl;
std::string text = buffer.str()
std::cout.rdbuf( old );
class CoutRedirect {
CoutRedirect(std::streambuf *newBuffer)
: old(std::cout.rdbuf(newBuffer)) {
}
~Cout_redirect() {
std::cout.rdbuf(old);
}
private:
std::streambuf *old;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment