a side-by-side reference sheet
grammar and execution | variables and expressions | arithmetic and logic | strings | regexes | dates and time | fixed-length arrays | resizable arrays | tuples | dictionaries | functions | execution control | exceptions | concurrency | file handles | files | file formats | directories | processes and environment | libraries and namespaces | user-defined types | generic types | objects | inheritance and polymorphism | reflection | net and web | unit tests | debugging and profiling
version | ||||
---|---|---|---|---|
c++ | objective c | java | c# | |
version used |
C++11 gcc 4.8 clang 3.5 |
gcc 4.2 | java 1.7 | mono 2.10 (C# 4.0) |
show version |
$ g++ --version | $ gcc --version | $ javac -version | $ mcs --version |
implicit prologue | #include <iostream> #include <string> using namespace std; |
|||
grammar and execution | ||||
c++ | objective c | java | c# | |
hello world | $ cat hello.cpp #include <iostream> using namespace std; int main(int argc, char** arg) { cout << "Hello, World!" << endl; } $ g++ -std=c++0x hello.cpp $ ./a.out |
$ cat hello.m #include <stdio.h> int main(int argc, char **argv) { printf("Hello, World!\n"); } $ gcc hello.m $ ./a.out |
$ cat Hello.java public class Hello { public static void main(String[] args) { System.out.println("Hello, World!"); } } $ javac Hello.java $ java Hello |
$ cat hello.cs using System; public class Hello { public static void Main() { Console.WriteLine("Hello, World!"); } } $ mcs hello.cs $ mono hello.exe |
file suffixes source, header, object file |
foo.cpp foo.h foo.o |
Foo.m Foo.h Foo.o |
Foo.java none Foo.class Foo.java must define a single top level class Foo |
Foo.cs none Foo.exe or Foo.dll although files are often named after a class they contain, this is not required |
block delimiters |
{ } | { } | { } | { } |
statement terminator |
; | ; | ; | ; |
top level statements | A source file will normally have #include directives at the top, followed by declarations, definitions, and namespaces containing declarations and definitions. After the preprocessor has finished processing a source file, the compilation unit will only contain declarations, definitions, and namespaces at the top level. |
each file contains the following elements in order: (1) optional package directive (2) zero or more import directives (3) one public class definition and zero or more private class definitions |
||
end-of-line comment |
// comment | // comment | // comment | // comment |
multiple line comment | /* comment another comment */ |
/* comment another comment */ |
/* comment another comment */ |
/* comment another comment */ |
variables and expressions | ||||
c++ | objective c | java | c# | |
local variable | int i; int j = 3; int k(7); |
int i; int j = 3; |
int i; int j = 3; |
int i; int j = 3; |
uninitialized local variable | The behavior is undefined. Most implementations do not zero-initialize stack variables, so the value will be whatever happened to be in memory. |
behavior is undefined. Most implementations do not zero-initialize stack variables, so the value will be whatever happened to be in memory. |
compiler error | compiler prevents use of uninitialized local variable |
global variable | // in foo.cpp and outside of any function // or class definition: int foo = 7; // in bar.cpp and outside of any function // or class definition: extern int foo; |
in foo.cpp outside of any function or class definition: int foo = 7; in bar.cpp outside of any function or class definition: extern int foo; |
foo/Foo.java: package foo; // globals must be declared inside a // class: public class Foo { public static int bar; } UseFoo.java: import foo.Foo; public class UseFoo { public static void main(String[] args) { System.out.println(Foo.bar); } } |
|
uninitialized global variable | Zero initialized: numeric types and pointers are set to zero. Classes, structs, and arrays have all of their members or elements zero-initialized recursively. | Zero initialized. | ||
write-once variable | const int i = 7; | const int i = 7; | final int i = 7; | const int i = 7; |
assignment | int n; n = 3; |
int n; n = 3; |
||
compound assignment arithmetic, bit |
+= -= *= /= %= <<= >>= &= ^= |= |
+= -= *= /= %= <<= >>= &= ^= |= >>= is arithmetic right shift, >>>= is logical right shift |
||
increment and decrement | int n = 1; int one = n++; int three = ++n; int two = --n; |
int n = 1; int one = n++; int three = ++n; int two = --n; |
||
address | int i(3); int* ip = &i; |
none | ||
dereference | int i(3); int* ip = &i; int i2 = *ip + 1; |
none | ||
type size | cout << sizeof(int) << endl; cout << sizeof(int*) << endl; |
none | ||
address arithmetic | none | |||
unique pointer | none | |||
reference count pointer | none | |||
weak pointer | none | |||
allocate heap | int* ip = new int; | #include <stdlib.h> int *ip = malloc(sizeof(int)); |
// Primitive types are stack allocated. // Use a wrapper class to store on the // heap: Integer i = new Integer(0); |
object i = 0; |
uninitialized heap | Memory allocated by the new operator is zero-initialized. | zero-initialized | ||
free heap | delete ip; | #include <stdlib.h> free(ip); |
garbage collected | garbage collected |
null |
NULL | NULL | null | null |
coalesce |
string s1 = s2 || "was null"; | NSString *s1 = s2 || @"was null"; | String s1 = s2 == null ? "was null" : s2; | string s1 = s2 ?? "was null"; |
arithmetic and logic | ||||
c++ | objective c | java | c# | |
boolean type |
bool | BOOL | boolean | bool |
true and false |
true false | YES NO | true false | true false |
falsehoods |
false 0 0.0 NULL | 0 0.0 NULL | false | false |
logical operators | && || ! and or not |
&& || ! | && || ! | && || ! |
relational operators | == != < > <= >= | == != < > <= >= | == != < > <= >= | == != < > <= >= |
integer type | signed char n1; // 1+ bytes short int n2; // 2+ bytes int n3; // 2+ bytes long int n4; // 4+ bytes long long int n5; // 4+ bytes |
signed char 1+ byte# short int 2+ bytes int 2+ bytes long int 4+ bytes long long int 4+ bytes |
byte n1; // 1 byte short n2; // 2 bytes int n3; // 4 bytes long n4; // 8 bytes |
sbyte 1 byte short 2 bytes int 4 bytes long 8 bytes |
unsigned type | unsigned char n1; // 1+ bytes unsigned short int n2; // 2+ bytes unsigned int n3; // 2+ bytes unsigned long int n4; // 4+ bytes unsigned long long int n5; // 4+ bytes |
unsigned char: 8+ unsigned short int 2 bytes+ unsigned int 2 bytes+ unsigned long int 4+ bytes unsigned long long int 4+ bytes |
char n1; //2 bytes | byte 1 byte ushort 2 bytes uint 4 bytes ulong 8 bytes |
float type | float x1; // 4 bytes double x2; // 8 bytes long double x3; // 16 bytes |
float double long double |
float x1; // 4 bytes double x2; // 8 bytes |
float 4 bytes double 8 bytes |
fixed type |
none | none | none | decimal 12 bytes |
arithmetic operators | + - * / % | + - * / % | + - * / % | + - * / % |
integer division | // evaluates to 2: 7 / 3 |
// evaluates to 2: 7 / 3 |
// evaluates to 2: 7 / 3 |
// evaluates to 2: 7 / 3 |
integer division by zero | process sent a SIGFPE signal | process sent a SIGFPE signal | throws java.lang.ArithmeticException | Syntax error if divisor is a constant. Otherwise throws System.DivideByZeroException |
float division |
7 / static_cast<float>(3) | 7 / (float)3 | 7 / (float)3 | 7 / (float)3 |
float division by zero dividend is positive, zero, negative |
inf nan -inf There are no portably defined literals or constants for the above values. |
inf nan -inf there are no portably defined literals or constants for the above values. |
Float.POSITIVE_INFINITY Float.NaN Float.NEGATIVE_INFINITY constants with same names defined in Double |
float.PositiveInfinity float.NaN float.NegativeInfinity constants with same names defined in double |
power | #include <cmath> double x = pow(2.0, 32.0); |
#include <math.h> pow(2.0, 32.0); |
Math.pow(2.0, 32.0); | System.Math.Pow(2.0, 32.0); |
sqrt | #include <cmath> double x = sqrt(2); |
#include <math.h> sqrt(2) |
Math.sqrt(2) | Math.Sqrt(2) |
sqrt -1 | nan | nan | Double.NaN | double.NaN |
transcendental functions | #include <cmath> exp log log2 log10 sin cos tan asin acos atan atan2 |
#include <math.h> exp log log2 log10 sin cos tan asin acos atan atan2 |
Math.exp Math.log none Math.log10 Math.sin Math.cos Math.tan Math.asin Math.acos Math.atan Math.atan2 |
using System; Math.Exp Math.Log none Math.Log10 Math.Sin Math.Cos Math.Tan Math.Asin Math.Acos Math.Atan Math.Atan2 |
transcendental constants | #include <cmath> double e = M_E; double pi = M_PI; |
#include <math.h> M_E M_PI |
Math.E Math.PI |
System.Math.E System.Math.PI |
float truncation towards zero, to nearest integer, towards -∞, towards ∞ |
#include <cmath> double x = 3.7; long trnc = static_cast<long>(x); long rnd = round(x); long flr = floorl(x); long cl = ceill(x); |
#include <math.h> double d = 3.77; long trnc = (long)d; long rnd = round(d); long flr = floorl(d); long cl = ceill(d); |
(long)3.77 Math.round(3.77) (long)Math.floor(3.77) (long)Math.ceil(3.77) |
using System; (long)3.77 Math.Round(3.77) Math.Floor(3.77) Math.Ceiling(3.77) |
absolute value | #include <cmath> // fabs() #include <cstdlib> // abs() int n = -7; int absn = abs(n); double x = -7.77; double absx = fabs(x); |
#include <stdlib.h> // abs() #include <math.h> // fabs() int i = -7; int ai = abs(i); float x = -7.77; float ax = fabs(x); |
Math.abs(-7) Math.abs(-7.77) |
System.Math.Abs(-7) System.Math.Abs(-7.77) |
integer overflow | modular arithmetic The C standard does not define behavior for signed integers, however. |
modular arithmetic The C standard does not define behavior for signed integers, however. |
modular arithmetic | modular arithmetic |
float overflow | no behavior defined by standard; many implementations return inf | no behavior defined by standard; many implementations return inf | Float.POSITIVE_INFINITY | float.PositiveInfinity |
float limits largest finite float, smallest positive float |
#include <cfloat> FLT_MAX FLT_MIN DBL_MAX DBL_MIN LDBL_MAX LDBL_MIN |
Float.MAX_VALUE Float.MIN_VALUE Double.MAX_VALUE Double.MIN_VALUE |
float.MaxValue float.Epsilon double.MaxValue double.Epsilon |
|
complex construction | #include <complex> complex<double> z(1.0, 2.0); |
|||
complex decomposition real and imaginary component, argument, absolute value, conjugate |
z.real() z.imag() arg(z) abs(z) conj(z) |
|||
random number uniform integer, uniform float, normal float |
#include <random> default_random_engine dre; uniform_int_distribution<int> uid(0, 99); uniform_real_distribution<double> urd(0.0, 1.0); normal_distribution<double> nd(0.0, 1.0); int i = uid(dre); double x = urd(dre); double y = nd(dre); |
#include <stdlib.h> // assuming 100 much smaller than RAND_MAX: int i = rand() % 100; double x = drand48(); none |
import java.util.Random; Random rnd = new Random(); int i = rnd.nextInt(100); double x = rnd.nextDouble(); double y = rnd.nextGaussian(); |
using System; Random rnd = new Random(); int i = rnd.Next(); double x = rnd.NextDouble(); none |
random seed | #include <random> // set seed in constructor: default_random_engine dre(17); // set seed of existing engine: dre.seed(17); |
import java.util.Random; Random rnd = new Random(); rnd.setSeed(17); // seed can also be passed to constructor |
using System; Random rnd = new Random(17); |
|
bit operators | << >> & | ^ ~ bitand bitor compl >> is arithmetic right shift on signed integers and logical right shift on unsigned integers |
<< >> & | ^ ~ | << >> & | ^ ~ >> is arithmetic right shift, >>> is logical right shift |
<< >> & | ^ ~ |
binary, octal, and hex literals | 0b0101010 052 0x2a |
none in Java 1.6 052 0x2a |
none 052 0x2a |
|
radix convert integer to and from string with radix |
Integer.toString(42, 7) Integer.parseInt("60", 7) |
|||
strings | ||||
c++ | objective c | java | c# | |
string type |
string s("lorem ipsum"); // convert to C string: const char* s2 = s.c_str(); |
NSString* s = @"lorem ipsum"; // convert to C string: const char* s2 = [s UTF8String]; |
java.lang.String | string |
string literal |
// const char*: "don't say \"no\"" |
@"don't say \"no"" | "don't say\"no\"" | "don't say \"no\"" |
newline in literal | Newlines in string literals are ignored. | string literals can extend over multiple lines, but the newlines do not appear in the resulting string | no | string literals can extend over multiple lines, but the newlines do not appear in the resulting string |
literal escapes |
\a \b \f \n \r \t \v \\ \" \' \xhh \o \oo \ooo |
\a \b \f \n \r \t \v \\ \" \' \xhh \o \oo \ooo |
\b \f \n \r \t \\ \" \' \uhhhh \o \oo \ooo |
\a \b \f \n \r \t \v \\ \" \' \xhh \xhhhh \o \oo \ooo |
allocate string | string* s = new string("hello"); | NSString *s = @"hello"; | String s = "hello"; String t = new String(s); |
string s = "hello"; string t = string.Copy(s); |
are strings mutable? | string s("bar"); s[2] = 'z'; |
String objects are immutable. StringBuffer has append(), delete(), deleteCharAt(), insert(), replace(), setCharAt(). |
||
copy string | string s("bar"); // use assignment or copy constructor: string s2 = s; string s3(s); // s contains "baz"; // s2 and s3 contain "bar": s[2] = 'z'; |
String s = "bar"; StringBuffer sb = new StringBuffer(s); sb.setCharAt(2, 'z'); // s contains "bar"; s2 contains "baz": String s2 = sb.toString(); |
||
format string | #include <sstream> ostringstream oss; oss << "Spain: " << 7; string s(oss.str()); |
[NSString stringWithFormat:@"%@: %d", @"Spain", 7] | String.format("%s: %d", "Spain", 7) | string.Format("{0}: {1}", "Spain", 7) |
compare strings | string s1("hello"); string s2("world"); // negative if s1 lexically before s2; // zero if s1 and s2 are equal: int result1 = s1.compare(s2); bool result2 = s1 == s2; |
[@"hello" compare:@"hello"] | "hello".compareTo("world") | "hello".CompareTo("world") |
concatenate and append |
string s("hello"); string s2 = s + " world"; s += " world"; |
NSString *s1 = @"hello"; NSString *s2 = @" world"; NSString *s3 = [s1 stringByAppendingString:s2]; |
"hello" + " world" | "hello" + " world" |
replicate |
string hbar(80, '-'); | import java.util.Arrays; char[] a = new char[80]; Arrays.fill(a, '-'); String s = new String(a); |
||
translate case | #include <algorithm> string s("foo"); // in place: transform(s.begin(), s.end(), s.begin(), ::toupper); transform(s.begin(), s.end(), s.begin(), ::tolower); // non-destructive: string s2; s2.resize(s.size(); transform(s.begin(), s.end(), s2.begin(), ::toupper); |
[@"HELLO" lowercaseString] | "hello".toUpperCase() "HELLO".toLowerCase() |
"hello".ToUpper() HELLO".ToLower() |
trim | #include <algorithm> string s(" hello "); // trim in place on left: s.erase( s.begin(), find_if( s.begin(), s.end(), not1(ptr_fun<int, int>(isspace)) ) ); // trim in place on right: s.erase( find_if( s.rbegin(), s.rend(), not1(ptr_fun<int, int>(isspace)) ).base(), s.end() ); |
[@" hello " stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceCharacterSet]] | " hello ".trim() | " hello ".Trim() |
pad on right, on left |
#include <iomanip> #include <sstream> string s("hello"); string rpad(s); rpad += string(10 - s.length(), ' '); ostringstream oss; oss << setw(10) << s; string lpad(oss.str()); |
[@"hello" stringByPaddingToLength:10 withString:@" " startingAtIndex:0] | "hello".PadLeft(10) | |
number to string | char buf[100]; long n = 123; sprintf(buf, "%ld", n); /* prevent buffer overflow: */ snprintf(buf, 100, "%ld", n); |
Integer.toString(14) Long.toString(14) Double.toString(14.7) |
14.ToString() 14.7.ToString() |
|
string to number | #include <sstream> stringstream ss("7 14.3 12"); int n1; double x; long n2; ss >> n1 >> x >> n2; |
[@"14" integerValue] [@"14" longLongvalue] [@"14.7" floatValue] [@"14.7" doubleValue] |
Byte.parseByte("14") Short.parseShort("14") Integer.parseInt("14") Long.parseLong("14") Float.parseFloat("14.7") Double.parseDouble("14.7") |
byte.Parse("14") short.Parse("14") int.Parse("14") long.Parse("14") float.Parse("14") double.Parse("14") decimal.Parse("14") |
join |
System.String.Join(", ", names) | |||
split | [@"Bob Ned Amy" componentsSeparatedByString:@" "] | "Bob Ned Amy".split(" ") | string[] names = "Bob Ned Amy".Split(' '); | |
serialize | ||||
string length |
string s("hello"); size_t len = s.length(); |
[s length] | s.length() | s.Length |
index of substring |
string("hello").find("ll") | [@"hello" rangeOfString:@"ll"].location | "hello".indexOf("ll") | "hello".IndexOf("ll") |
extract substring | string("hello").substr(2, 2) | [@"hello" substringWithRange:NSMakeRange(2, 2)] | "hello".substring(2,4) | "hello".Substring(2, 2) |
character type | char wchar_t |
char Character |
char Char |
|
character literal | char n = 'X'; | char n = 'X'; | char n = 'X'; | |
test character letter, digit, whitespace, uppercase letter, lowercase letter |
// functions have this signature: // // int (*)(int): // isalpha isdigit isspace isupper islower |
System.Char.IsLetter(Char) System.Char.IsNumber(Char) System.Char.IsWhiteSpace(Char) System.Char.IsUpper(Char) System.Char.IsLower(Char) |
||
regular expressions | ||||
c++ | objective c | java | c# | |
regex type | regex wregex |
|||
character class abbreviations | . \d \D \s \S \w \W | |||
anchors | ^ $ \b \B | |||
lookahead positive, negative |
(?=subpattern) (?!subpattern) |
|||
match test | #include <regex> regex rx(".*ll.*"); bool match = regex_match("hello", rx); |
NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", @".*ll.*"]; BOOL is_match = [pred evaluateWithObject:@"hello"]; |
boolean isMatch = "hello".matches(".*ll.*"); | using System.Text.RegularExpressions; Regex regex = new Regex("ll"); bool isMatch = regex.IsMatch("hello"); |
case insensitive match test | #include <regex> regex rx("lorem", icase); bool match = regex_match("Lorem", rx); |
|||
modifiers | ||||
substitution | String s1 = "hello".replace("ll","LL"); String s2 = "hello".replaceAll("l","L"); |
using System.Text.RegularExpressions; Regex r1 = new Regex("ll"); String s1 = r1.Replace("hello", "LL", 1); Regex r2 = new Regex("l"); String s2 = r2.Replace("hello", "L"); |
||
match, prematch, postmatch | ||||
group capture | ||||
dates and time | ||||
c++ | objective c | java | c# | |
date and time type |
java.util.Date | System.DateTime | ||
current date and time | import java.util.Date; long millis = System.currentTimeMillis(); Date dt = new Date(millis); |
using System; DateTime dt = DateTime.Now; |
||
to unix epoch, from unix epoch | long epoch = dt.getTime() / 1000; Date dt2 = new Date(epoch * 1000); |
using System; long tenM = 10 * 1000 * 1000; long sec = dt.ToFileTimeUtc() / tenM; long epoch = sec - 11644473600; long ft = (epoch + 11644473600) * tenM; DateTime dt2 = DateTime.FromFileTimeUtc(ft); |
||
date and time to string | dt.toString() | dt.ToString() | ||
format date | String s = "yyyy-MM-dd HH:mm:ss"; DateFormat fmt = new SimpleDateFormat(s); String s2 = fmt.format(dt); |
String s = "yyyy-MM-dd HH:mm:ss"); String s2 = dt.ToString(s); |
||
parse date | String s = "2011-05-03 17:00:00"; Date dt2 = fmt.parse(s); |
using System; using System.Globalization; CultureInfo enUS = new CultureInfo("en-US"); DateTime dt2 = DateTime.ParseExact( "2011-05-03 17:00:00", "yyyy-MM-dd HH:mm:ss", enUS); |
||
date subtraction | difference in milliseconds as a long: dt2.getTime() - dt.getTime() |
|||
add duration | long day_ms = 24 * 3600 * 1000; Date dt = new Date(dt.getTime() + day_ms)); |
|||
date parts | import java.util.Date; import java.util.Calendar; import java.util.GregorianCalendar; Date dt = new Date(); GregorianCalendar cal = new GregorianCalendar(); cal.setTime(dt); cal.get(Calendar.YEAR) cal.get(Calendar.MONTH) + 1 cal.get(Calendar.DAY_OF_MONTH) |
|||
time parts | import java.util.Date; import java.util.Calendar; import java.util.GregorianCalendar; Date dt = new Date(); GregorianCalendar cal = new GregorianCalendar(); cal.setTime(dt); cal.get(Calendar.HOUR_OF_DAY) cal.get(Calendar.MINUTE) cal.get(Calendar.SECOND) |
|||
build broken-down datetime | import java.util.GregorianCalendar; int yr = 2015, mo = 5, dy = 31; int hr = 9, mi = 0, ss = 0; GregorianCalendar cal = new GregorianCalendar(yr, mo - 1, dy, hr, mi, ss); Date dt = cal.getTime(); |
|||
fixed-length arrays | ||||
c++ | objective c | java | c# | |
declare on stack | int a[10]; | int a[10]; | arrays must be allocated on heap | arrays must be allocated on heap |
declare on heap | int* a = new int[10]; | #include <stdlib.h> int *a = calloc(10, sizeof(int)); |
int[] a = new int[10]; | int[] a = new int[10]; |
free heap | delete[] a; | #include <stdlib.h> free(a); |
garbage collected | garbage collected |
initialization list | int a[] = {1, 2, 3}; | NSArray *a = [NSArray arrayWithObjects:@"hello", @"goodbye", nil]; | int[] a = {1,2,3}; | int[] a = {1,2,3}; |
size | int a[10]; // stack arrays only: size_t len = sizeof(a) / sizeof(a[0]); |
[a count] | a.length | a.Length |
lookup |
int first = a[0]; | [a objectAtIndex:0] | a[0] | a[0] |
update |
a[0] = 7; | |||
out-of-bounds | No defined behavior An out-of-bounds lookup may return the value the memory location contains; an out-of-bounds update may cause memory corruption. The system may detect an invalid address and send the process a SIGSEGV. |
raises NSRangeException exception | ArrayIndexOutOfBoundsException | IndexOutOfRangeException |
copy | const size_t LEN(4); int src[LEN] = {3, 2, 4, 1}; int dest[LEN]; // 3rd arg is number of bytes to copy: memcpy(dest, src, LEN * sizeof(src[0])); |
|||
as function argument | void reverse(int* a, size_t len) { for (int i = 0; i < len / 2; ++i) { int tmp = a[len - i - 1]; a[len - i - 1] = a[i]; a[i] = tmp; } } const size_t LEN(4); int a[LEN] = {3, 2, 4, 1}; reverse(a, LEN); |
|||
iterate | const size_t LEN(4); int a[LEN] = {3, 2, 4, 1}; for (int i = 0; i < LEN; ++i) { cout << "value at " << i << " is " << a[i] << endl; } |
NSEnumerator *i = [a objectEnumerator]; id o; while (o = [i nextObject]) { do something with o } |
for (String name : names) { | foreach (string name in names) { |
sort | #include <cstdlib> int comp(const void* ap, const void* bp) { int a = *(int*)ap; int b = *(int*)bp; return a < b ? -1 : (a == b ? 0 : 1); } const size_t LEN(4); int a[LEN] = {3, 2, 1, 4}; qsort(a, LEN, sizeof(a[0]), &comp); |
|||
resizable arrays | ||||
c++ | objective c | java | c# | |
declare | #include <vector> vector <int> a; |
NSMutableArray *a = [NSMutableArray arrayWithCapacity:10]; | java.util.Vector<String> vec = new java.util.Vector<String>(); | using System.Collections.Generic; List<string> l = new List<string>(); |
initialization list | #include <vector> vector<int> a = {1, 2, 3}; vector<int> a2({7, 8, 9}); |
|||
size |
size_t len = a.size(); | [a count] | vec.size() | l.Count |
capacity get, increase |
size_t cap = a.capacity(); // will not decrease capacity: a.reserve(10); |
|||
empty test and clear |
bool is_empty = a.empty(); a.clear(); |
|||
lookup | int n = a[0]; // can raise out_of_range: int n2 = a.at(0); |
[a objectAtIndex:0] | vec.elementAt(0) | l[0] |
update |
a[2] = 4; | |||
out-of-bounds behavior | using [] with out-of-bounds index has undefined behavior | raises NSRangeException | throws ArrayIndexOutOfBoundsException | throws System.ArgumentOutOfRangeException |
element index | #include <vector> vector<int> a({6, 7, 8, 9}); auto iter = find(a.cbegin(), a.cend(), 8); if (iter != a.cend()) { size_t pos = *iter; } |
|||
slice | #include <vector> vector<int> a({6, 7, 8, 9}); // a2 contains {7, 8}: vector<int> a2(a.cbegin() + 1, a.cbegin() + 3); |
|||
slice to end | #include <vector> vector<int> a({6, 7, 8, 9}); // a2 contains {7, 8, 9}: vector<int> a2(a.cbegin() + 1, a.cend()); |
|||
manipulate back | #include <vector> vector<int> a({6, 7, 8}); a.push_back(9); int elem = a.pop_back(); |
[a addObject:@"hello"]; [a removeLastObject]; |
vec.add("hello"); or vec.add(vec.size(), "hello"); vec.removeElementAt(vec.size()-1); |
l.Add("hello"); l.RemoveAt(l.Count - 1); |
manipulate front | #include <vector> vector<int> a({6, 7, 8}); // slower than manipulating back: a.insert(a.cbegin(), 5); int elem = a[0]; a.erase(a.cbegin()); |
|||
concatenate | #include <vector> vector<int> a1({1, 2, 3}); vector<int> a2({4, 5, 6}); a1.insert(a1.cend(), a2.cbegin(), a2.cend()); |
|||
replicate element | #include <vector> // array of 10 zeros: vector<int> a(10, 0); |
|||
copy | #include <vector> vector<int> a({1, 2, 3}); // copy constructor: vector<int> a2(a); vector<int> a3; // assignment performs copy: a3 = a; |
|||
array as function argument | use reference or pointer to avoid copying array | |||
iterate | #include <vector> int sum(0); vector<int> a({1, 2, 3}); for (const auto& n: a) { sum += n; } |
NSEnumerator *i = [a objectEnumerator]; id o; while (o = [i nextObject]) { do something with o } |
for ( String s : vec ) { do something with s } |
foreach ( string s in l ) { do something with s } |
iterate over elements and indices | #include <vector> vector<int> a({6, 7, 8}); for (auto iter = a.cbegin(); iter != a.cend(); ++iter) { cout << "value at " << iter - a.cbegin() << " is " << *iter << endl; } |
|||
reverse | #include <vector> vector<int> a({1, 2, 3}); vector<int> a2(a.crbegin(), a.crend()); |
|||
sort | #include <vector> vector<int> a({3, 2, 4, 1}); sort(a.begin(), a.end()); |
|||
dedupe | #include <set> #include <vector> vector<int> a({1, 1, 2, 2, 3}); set<int> tmp(a.cbegin(), a.cend()); // often unnecessary since sets provide // many of the same methods as vectors: vector<int> a2(tmp.cbegin(), tmp.cend()); |
|||
membership | #include <vector> vector<int> a({1, 2, 3}); if (find(a.cbegin(), a.cend(), 7) != a.cend()) { cout << "contains 7" << endl; } |
|||
tuples | ||||
c++ | objective c | java | c# | |
constructor | tuple<string, int, float> tup("foo", 1, 3.7); // invokes default constructors for elements: tuple<string, int, float> tup2; // element types are inferred: auto tup3 = make_tuple("foo", 1, 3.7); |
|||
lookup | tuple<string, int, float> tup("foo", 1, 3.7); string s = get<0>(tup); int i = get<1>(tup); float x = get<2>(tup); |
|||
decompose | tuple<string, int, float> tup("foo", 1, 3.7); string s; float x; tie(s, ignore, x) = tup; |
|||
update |
get<0>(tup) = "bar"; | |||
length |
tuple_size<decltype(tup)>::value | |||
pair constructor | pair <string, int> p2("foo", 7); // invokes default constructors for elements: pair <string, int> p1; // element types are inferred: auto p3 = make_pair("foo", 7); |
using System.Collections.Generic; KeyValuePair<string,int> pr = new KeyValuePair<string,int>("hello",5); System.Console.WriteLine("{0} {1}", pr.Key, pr.Value); |
||
pair lookup | auto p = make_pair("foo", 7); string s = p.first; int i = p.second; |
|||
pair update | p.first = "bar"; p.second = 8; |
|||
dictionaries | ||||
c++ | objective c | java | c# | |
constructor | #include <map> map<string, int> m; |
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity:10]; | java.util.TreeMap<String, Integer> m = new java.util.TreeMap<String, Integer>(); | using System.Collections.Generic; Dictionary<string, int> dict = new Dictionary<string, int>(); |
lookup | m["hello"] = 5; cout << m["hello"] << endl; |
[dict setObject:@"5" forKey:@"hello"]; [dict objectForKey:@"hello"] |
m.put("hello", 5); m.get("hello") |
dict.Add("hello", 5); dict["hello"] |
size |
m.size() | [dict count] | m.size() | dict.Count |
delete |
m.erase(m.find("hello")); | [dict removeObjectForKey:@"hello"]; | m.remove("hello"); | dict.Remove("hello"); |
missing key behavior | returns element created by default constructor of value type | NULL | null | throws KeyNotFoundException in System.Collections.Generic |
iterate | map<string,int>::iterator mi; for (mi = m.begin(); mi != m.end(); ++mi) { printf("%s %d", mi->first, mi->second) } |
NSEnumerator *i = [dict keyEnumerator]; id key; while ((key = [i nextObject])) { do something with key } |
for ( java.util.Map.Entry<String, Integer> e : m.entrySet() ) { use e.getKey() or e.getValue() } |
foreach ( KeyValuePair<string,int> e in dict) { use e.Key and e.Value } |
functions | ||||
c++ | objective c | java | c# | |
declare | // parameter names are optional: int add(int m, int n); |
|||
define | int add(int m, int n) { return m + n; } |
|||
call |
int sum = add(3, 7); | |||
define static class method | // Ops.h: class Ops { public: static int add(int m, int n); }; // Ops.cpp: int Ops::add(int m, int n) { return m + n; } |
|||
invoke static class method | int sum = Ops::add(3, 7); // class name not needed // inside class namespace: int sum = add(3, 7); |
|||
overload | int add(int m, int n) { return m + n; } float add(float x, float y) { return x + y; } |
method overloading only | yes | yes |
default argument | #include <cmath> float logarithm(float x, float base = 10.0) { return log(x) / log(base); } |
none | use method overloading | use method overloading |
variable number of arguments | use C; use method overloading for finite arities | public static String concat(String first, String… rest) { StringBuilder sb = new StringBuilder(first); for (String arg: rest) { sb.append(arg); } return sb.toString(); } String s = Concat.concat("Hello", ", ", "World", "!"); |
public static string concat(params string[] args) { return System.String.Join("",args); } string s = Concat.concat("Hello", ", ", "World", "!") |
|
named parameters | none | +(float)weight: (float) w height: (float) h { return (w * 703) / (h * h); } +(float)height: (float) h weight: (float) w { return [BMI weight: w height: h]; } [BMI weight:155 height:70]; [BMI height:70 weight:155]; |
none | added in C# 4.0: static int BMI(int weight, int height) { return (weight * 703) / (height * height); } BMI(weight: 123, height: 64); BMI(height: 64, weight: 123); |
pass by value | int add1(int n) { return ++n; } int i(7); // set i2 to 8 w/o modifying i: int i2 = add1(i); |
void use_integer(int i) { function body } int i = 7; use_integer(i); |
primitive types are always passed by value | primitive types are always passed by value |
pass by reference | int add1(int& n) { return ++n; } int i(7); // set i and i2 to 8: int i2 = add1(i); |
none | objects and arrays are always passed by reference | objects and arrays are always passed by reference also out parameter |
pass by address | int add1(int* n) { return ++*n; } int i(7); // set i and i2 to 8: int i2 = add1(&i); |
void use_iptr(int *i) { function body } int i = 7; use_iptr(&i); |
none | none |
return value |
argument of return; type must be declared | |||
no return value | void message(const string& msg) { cout << msg << endl; } |
|||
recursive function | int factorial(int n) { if (n <= 1) { return 1; } return n * factorial(n - 1); } |
|||
anonymous function | auto add = [](int n, int m) { return n + m; }; |
|||
invoke anonymous function | //on variable holding anon. function: int sum = add(3, 7); // on lambda expression: int sum2 = [](int n, int m) { return n + m; }(3, 7); |
|||
closure | ||||
function with private state | int counter() { static int i = 0; return ++i; } |
|||
function as value | ||||
overload operator | Rational Rational::operator+(Rational& o) { return Rational(this->num * o.denom + o.num * this->denom, this->denom * o.denom); } |
none | none | public static Rational operator+(Rational a, Rational b) { return new Rational(a.num*b.denom + b.num *a.denom,a.denom*b.denom); } |
execution control | ||||
c++ | objective c | java | c# | |
if | int signum; if (n > 0) { signum = 1; } else if (n == 0) { signum = 0; } else { signum = -1; } |
if (i>0) { signum = 1; } else if (i==0) { signum = 0; } else { signum = -1; } |
if (i>0) { signum = 1; } else if (i==0) { signum = 0; } else { signum = -1; } |
if (i>0) { signum = 1; } else if (i==0) { signum = 0; } else { signum = -1; } |
dangling else | if (n == 0) if (m == 0) cout << "n and m are zero" << endl; else cout << "n is zero; m isn't" << endl; |
|||
switch | const int INVALID_BINARY_DIGIT(-1); int bin_digit; switch(n) { case 0: case 1: bin_digit = n; break; default: bin_digit = INVALID_BINARY_DIGIT; break; } |
switch(i) { case 0: 0; break; case 1: 1; break; default: -1; break; } |
switch(i) { case 0: 0; break; case 1: 1; break; default: -1; break; } |
switch(i) { case 0: 0; break; case 1: 1; break; default: -1; break; } |
while | int i(1), fact(1), n(10); while (i < n) { fact *= i; ++i; } |
int i = 0; while (i<10) { … i++; } |
int i = 0; while (i<10) { … i++; } |
int i = 0; while (i<10) { … i++; } |
for | int fact, n(10); for (int i = 1, fact = 1; i <= n; ++i) { fact *= i; } |
int i, n; for (i=1,n=1; i<=10; i++) { n *= i; } |
int n = 1; for (int i=1; i<=10; i++) { n *= i; } |
int i, n; for (i=1,n=1; i<=10; i++) { n *= i; } |
break | int data[4] = {3, 2, 0, 1}; int i; bool has_zero(false); for (i = 0; i < 4; ++i) { if (data[i] == 0) { has_zero = true; break; } } |
|||
break out of nested loops | int data[2][2] = {{3, 2}, {0, 1}}; int i, j; bool has_zero(false); for (i = 0; i < 2; ++i) { for (j = 0; j < 2; ++j) { if (data[i][j] == 0) { has_zero = true; goto end_of_loops; } } } :end_of_loops |
|||
continue | int a[4] = {3, 2, 0, 1}; for (int i = 0; i < 4; ++i) { if (a[i] == 0) { continue; } cout << 1.0 / a[i] << endl; } |
|||
goto | ||||
exceptions | ||||
c++ | objective c | java | c# | |
base exception | Any type can be thrown. All exceptions thrown by the language or the standard library derive from exception, defined in <exception>. |
Any type which implements the interface java.lang.Throwable can be thrown. Exceptions thrown by the language and the standard libraries derive from java.lang.Errror or java.lang.Exception. |
||
predefined exceptions | #include <exception> #include <stdexcept> #include <system_error> #include <typeinfo> exception logic_error domain_error invalid_argument length_error out_of_range runtime_error system_error ios_base::failure bad_cast bad_exception bad_alloc |
java.lang.Throwable java.lang.Error java.lang.Exception java.lang.IOException java.lang.RuntimeException java.lang.ArithmeticException java.lang.IllegalArgumentException java.lang.IndexOutOfBoundsException java.lang.NullPointerException |
||
raise exception | #include <cstdlib> #include <stdexcept> void risky() { if (rand() < 10) { throw runtime_error("bam!"); } } |
NSException *exc = [NSException exceptionWithName:@"error" reason:@"failed" userInfo:nil]; @throw exc; |
throw new Exception("failed"); | throw new System.Exception("failed"); |
handle exception | #include <stdexcept> try { risky(); } catch (const exception &e) { cout << e.what() << endl; } |
@try { [NSException raise:@"error" format:@"failed"]; } @catch (NSException *e) { printf([[e reason] UTF8String]); } |
try { throw new Exception("failed"); } catch (Exception e) { System.out.println(e.getMessage()); } |
try { throw new System.Exception("failed"); } catch (System.Exception e) { System.Console.WriteLine(e.Message); } |
define exception | #include <stdexcept> class Bam : public runtime_error { public: Bam() : runtime_error("bam!") {} }; throw Bam(); |
|||
re-raise exception | #include <stdexcept> try { risky(); } catch (const exception& e) { cout << "an error occurred..." << endl; throw; } |
|||
catch-all handler | #include <stdexcept> try { risky(); } catch (...) { cout << "an error was ignored" << endl; } |
|||
multiple handlers | #include <stdexcept> try { risky(); } catch (const system_error &e) { cout << "system error: " << e.name() << endl; } catch (const exception &e) { cout << "exception: " << e.what() << endl; } catch (...) { cout << "unknown error" << endl; } |
|||
uncaught exception behavior | calls terminate() which by default calls abort() | |||
error message | #include <exception> try { risky(); } catch (const exception &e) { const chae *msg = e.what(); } |
|||
system call errno | #include <system_error> try { risky(); } catch (const system_error &e { int err_code_val = e.code().value(); } |
|||
finally clause | none | @try { risky code } @finally { perform cleanup } |
try { risky code } finally { perform cleanup } |
try { risky code } finally { perform cleanup } |
exception specification | // Use noexcept to declare that a function // does not raise exceptions; // declaring which exceptions a function // raises is deprecated in C++11. int add(int a, int b) noexcept { return a + b; } |
no | yes | no |
concurrency | ||||
c++ | objective c | java | c# | |
start thread |
||||
terminate current thread | ||||
terminate other thread | ||||
list threads | ||||
wait on thread |
||||
lock | ||||
create message queue | ||||
send message | ||||
receive message | ||||
file handles | ||||
c++ | objective c | java | c# | |
standard file handles | cin cout cerr clog // buffered cerr by default |
System.in System.out System.err |
||
read line from stdin | string s; cin >> s; |
|||
write formatted string to stdout |
cout << "count: " << 7 << endl; | printf("count: %d\n", 7); | System.out.printf("count: %d", 7); | System.Console.WriteLine("count: {0}", 7); |
read from file | #include <fstream> string line; ifstream f("/etc/passwd"); if (f.is_open()) { while (!f.eof()) { getline(f, line); // process line } f.close(); if ( 0 != f.fail() ) { // handle error } } else { // handle error } |
NSError *error = nil; NSString *s = [NSString stringWithContentsOfFile: @"/etc/passwd" encoding:NSUTF8StringEncoding error:&error]; if ( error != nil ) { // handle error } NSArray *a = [s componentsSeparatedByString:@"\n"]; id line; while (line = [i nextObject]) { // process line } |
import java.io.BufferedReader; import java.io.FileReader; BufferedReader in = new BufferedReader(new FileReader("/etc/passwd")); String line; while ((line = in.readLine()) != null) { // process line } |
using System.IO; StreamReader sr = new StreamReader("/etc/passwd"); string line; while ((line = sr.ReadLine()) != null) { // process line } |
write to file | #include <fstream> ofstream f("/tmp/test4"); int i; for (i = 0; i < 10; ++i) { f << i << endl; } f.close(); if (0 != f.fail()) { // handle error } |
import java.io.BufferedWriter; import java.io.FileWriter; BufferedWriter fout = new BufferedWriter(new FileWriter("/tmp/test2")); int i; for (i = 0; i < 10; i++) { fout.write(String.format("%d", i)); fout.newLine(); } fout.close(); |
using System.IO; StreamWriter fout = new StreamWriter("/tmp/test3"); int i; for (i = 0; i < 10; i++) { fout.WriteLine(i.ToString()); } fout.Close(); |
|
files | ||||
c++ | objective c | java | c# | |
file exists test, file regular test | import java.io.File; File f = new File("/etc/hosts"); f.exists() f.isFile() |
System.IO.File.Exists("/etc/hosts") | ||
file size | import java.io.File; File f = new File("/etc/hosts"); f.length() |
|||
is file readable, writable, executable | import java.io.File; File f = new File("/etc/hosts"); f.canRead() f.canWrite() f.canExecute() |
|||
set file permissions | import java.io.File; File f = new File("/tmp/foo"); // sets owner perms; to turn perms off // set arg to false: f.setReadable(true); f.setWritable(true); f.setExecutable(true); // if 2nd arg is false, perms are // for owner, group, and other: f.setReadable(true, false); f.setWritable(true, false); f.setExecutable(true, false); |
|||
copy file, remove file, rename file | import java.io.File; ?? File f2 = new File("/tmp/foo"); f2.delete(); File f3 = new File("/tmp/bar"); f3.renameTo(new File("/tmp/bar")); |
|||
file formats | ||||
c++ | objective c | java | c# | |
csv | ||||
json | ||||
build xml | ||||
parse xml | ||||
parse html | ||||
directories | ||||
c++ | objective c | java | c# | |
build pathname | import java.io.File; File root = File.listRoots()[0]; File etc = new File(root, "etc"); File hosts = new File(etc, "hosts"); String path = hosts.getPath(); |
|||
dirname and basename | #include <libgen.h> string s1 = dirname("/etc/hosts"); string s2 = basename("/etc/hosts"); |
import java.io.File; File f = new File("/etc/hosts"); String dirname = f.getParent(); String basename = f.getName(); |
||
absolute pathname | #include <climits> #include <cstdlib> char buf[PATH_MAX]; if (realpath("..", buf) == NULL) { throw exception(); } else { string path(buf); } |
import java.io.File; File f = new File("foo"); String abspath = f.getAbsolutePath(); // getCanonicalPath() expands .. and .: File f2 = new File("../foo"); String abspath2 = f2.getCanonicalPath(); File f3 = new File("./foo"); String abspath3 = f3.getCanonicalPath(); |
||
iterate over directory by file | import java.io.File; File dir = new File("/etc"); // iterate over names: for (String name: dir.list()) { System.out.println(name); } // iterate over file objects: for (File f: dir.listFiles()) { System.out.println(f.getName()); } |
|||
glob paths | ||||
make directory | import java.io.File; File f = new File("/tmp/foo/bar"); f.mkdirs(); |
|||
recursive copy | ||||
remove empty directory | ||||
remove directory and contents | ||||
directory test |
import java.io.File; File f = new File("/tmp"); f.isDirectory() |
|||
generate unused directory name | ||||
system temporary file directory | ||||
processes and environment | ||||
c++ | objective c | java | c# | |
signature of main | int main(int argc, char** argv) { | int main(int argc, char **argv) { | public class Foo { public static void main(String[] args) { |
public class Foo { public static void Main(string[] args) { |
first argument |
pathname of executable | pathname of executable | first command line argument | first command line argument |
environment variable | #include <stdlib.h> char* home = getenv("HOME"); setenv("EDITOR", "emacs", 1); unsetenv("EDITOR"); |
NSString *home = [[[NSProcessInfo processInfo] environment] objectForKey:@"HOME"]; | String home = System.getenv("HOME"); | using System.Environment; string home = GetEnvironmentVariable("HOME"); SetEnvironmentVariable("EDITOR", "emacs"); SetEnvironmentVariable("EDITOR", null); |
iterate through environment variables | NSEnumerator *i = [[[NSProcessInfo processInfo] environment] keyEnumerator]; id key; while ((key = [i nextObject])) { use NSString key } |
import java.util.Map; Map<String, String> env = System.getenv(); for (String name : env.keySet()) { String value = env.get(name)); } |
using System.Collections; using System.Environment; IDictionary env = GetEnvironmentVariables(); foreach (DictionaryEntry de in env) { use de.Key or de.Value } |
|
libraries and namespaces | ||||
c++ | objective c | java | c# | |
standard library name | C++ Standard Library | Foundation Framework | Java API | Base Class Library |
declare namespace | namespace foo { namespace bar { class Baz { static const int ANSWER = 42; }; } } |
package foo.bar; public class Baz { public static final int ANSWER = 42; } |
namespace foo { namespace bar { public class Baz { public const int ANSWER = 42; }; } } |
|
multiple namespaces per file | yes | no | yes | |
namespaces map to directories | no | yes | no | |
import namespace | using namespace foo::bar; cout << Baz::ANSWER << endl; |
import foo.bar.*; System.out.println(Baz.ANSWER); |
using foo.bar; System.Console.WriteLine(Baz.ANSWER); |
|
import part of namespace | using namespace foo; cout << bar::Baz::ANSWER << endl; |
none | none | |
import symbol | using foo::bar::Baz; cout << Baz::ANSWER << endl; |
import foo.bar.Baz; System.out.println(Baz.ANSWER); |
none | |
import static symbol | none | import static foo.bar.Baz.ANSWER; System.out.println(ANSWER); |
none | |
import position |
anywhere a statement is legal | after package and before type definitions | outside of class definitions | |
using a symbol that hasn't been imported | cout << foo::bar::Baz::ANSWER << endl; | System.out.println(foo.bar.Baz.ANSWER); | using System.Console; WriteLine(foo.bar.Baz.ANSWER); |
|
application environment | ||||
multiple installations | set JAVA_HOME environment variable to directory containing a bin subdirectory with java, javac, and other command line tools. Put $JAVA_HOME/bin at front of search path. | |||
package manager | ||||
user-defined types | ||||
c++ | objective c | java | c# | |
typedef | typedef int customer_id; customer_id cid = 3; |
typedef int customer_id; customer_id cid = 3; |
none | none |
enum | enum day_of_week { mon, tue, wed, thu, fri, sat, sun }; day_of_week d = tue; |
enum day_of_week { mon, tue, wed, thu, fri, sat, sun }; enum day_of_week d = tue; |
public enum DayOfWeek { MON, TUE, WED, THU, FRI, SAT, SUN }; DayOfWeek d = DayOfWeek.TUE; |
public enum DayOfWeek { MON, TUE, WED, THU, FRI, SAT, SUN }; DayOfWeek d = DayOfWeek.TUE; |
struct definition | class MedalCount { public: const char *country; int gold; int silver; int bronze; }; |
struct medal_count { const char* country; int gold; int silver; int bronze; }; |
public class MedalCount { public String country; public int gold; public int silver; public int bronze; } |
public class MedalCount { public string country; public int gold; public int silver; public int bronze; } |
struct declaration | MedalCount spain; | struct medal_count spain; | MedalCount spain = new MedalCount(); | MedalCount spain = new MedalCount(); |
struct initialization | MedalCount spain = { "Spain", 3, 7, 4 }; | struct medal_count spain = { "Spain", 3, 7, 4}; struct medal_count france = { .gold = 8, .silver = 7, .bronze = 9, .country = "France" }; |
no object literal syntax; define a constructor | no object literal syntax; define a constructor |
struct member assignment | spain.country = "Spain"; spain.gold = 3; spain.silver = 7; spain.bronze = 4; |
spain.country = "Spain"; spain.gold = 3; spain.silver = 7; spain.bronze = 4; |
spain.country = "Spain"; spain.gold = 3; spain.silver = 7; spain.bronze = 4; |
spain.country = "Spain"; spain.gold = 3; spain.silver = 7; spain.bronze = 4; |
struct member access | int spain_total = spain.gold + spain.silver + spain.bronze; | int spain_total = spain.gold + spain.silver + spain.bronze; | int spain_total = spain.gold + spain.silver + spain.bronze; | int spain_total = spain.gold + spain.silver + spain.bronze; |
generic types | ||||
c++ | objective c | java | c# | |
define generic type | template <class A> class Foo { public: A a; Foo(A a); }; template <class A> Foo<A>::Foo(A a) : a(a) { } |
public class Foo<A> { public A a; public Foo(A a) { this.a = a; } } |
public class Foo<A> { public A a; public Foo(A a) { this.a = a; } } |
|
instantiate generic type | Foo<string> f = Foo<string>("foo"); | Foo<String> f = new Foo<String>("foo"); | Foo<string> f = new Foo<string>("foo"); | |
generic function | template <class C> C add(C a, C b) { return a + b; } |
|||
generic array | template <class C> class Foo { public: C a[10]; }; |
not permitted. Use Object as the element type for the array or use an ArrayList. | public class Bar<C> { public C[] a; public Bar(C c) { this.a = new C[10]; } } |
|
value parameter | template <int N> int add(int i) { return N+i; } cout << add<7>(3) << endl; |
|||
template parameter | ||||
template specialization | ||||
multiple type parameters | template <class A, class B> class Pair { public: A a; B b; Pair(A a, B b); }; template <class A, class B> Pair<A, B>::Pair(A a, B b) : a(a), b(b) { } Pair<int, string> p = Pair<int, string>(7, "foo"); |
|||
generic type parameters | Pair<int, Foo<string> > p = Pair<int, Foo<string> >( 7, Foo<string>("foo")); |
|||
template parameters | ||||
variadic template | ||||
objects | ||||
c++ | objective c | java | c# | |
semantics of == | value comparison | object identity comparison | object identity comparison | value comparison |
define class | Rational.hpp: class Rational { public: int num, denom; Rational(int num, int denom); virtual ~Rational(); Rational operator+(Rational& addend); static Rational max(Rational& a, Rational& b); }; |
Rational.h: #import <Foundation/Foundation.h> @interface Rational : NSObject { int num; int denom; } @property int num, denom; -(Rational*) initWith: (int) n: (int) d; -(Rational*) add: (Rational *) o; @end Rational.m: #include "Rational.h" @implementation Rational @synthesize num, denom; -(Rational*) add: (Rational*) o { int sum_n = self.num * o.denom + o.num * self.denom; int sum_d = self.denom * o.denom; Rational* sum = [[Rational alloc] initWith: sum_n: sum_d]; return sum; } @end |
public class Rational { public int num; public int denom; public Rational add(Rational o) throws Exception { return new Rational(this.num*o.denom + o.num*this.denom,this.denom*o.denom); } public static Rational max(Rational a, Rational b) { return (a.num*b.denom > a.num*b.denom) ? a : b; } } |
public class Rational { public int num; public int denom; } |
class definition location | top level, class block, or function block | top level | top level, class block, or function block for anonymous classes | |
constructor | Rational::Rational(int n, int d) : num(n), denom(d) { if (denom == 0) { throw "zero denominator"; } int div = gcd(n,d); num = num / div; denom = denom / div; } |
-(Rational*) initWith: (int) n: (int) d { self = [super init]; if (self) { self.num = n; self.denom = d; } return self; } |
public Rational(int n, int d) throws Exception { if (d == 0) { throw new Exception("zero denominator"); } if ( d < 0 ) { this.num = -1 * n; this.denom = -1 * d; } else { this.num = n; this.denom = d; } } |
public Rational(int n, int d) { if (0 == d) { throw new System.Exception("zero denominator"); } if (d < 0) { this.num = -1 * n; this.denom = -1 * d; } else { this.num = n; this.denom = d; } } |
create object | Rational r1(7, 3); Rational* r2 = new Rational(8, 5); |
Rational *r = [[Rational alloc] initWith: 7: 3]; | Rational r = new Rational(7,3); | Rational r = new Rational(7,3); |
destructor | Rational::~Rational() {}; | -(void) dealloc { [super dealloc]; printf("deallocated…"); } |
protected void finalize() throws Throwable { super.finalize(); } |
~Rational() { perform cleanup } |
destroy object |
delete r2; | [r release]; | none | none |
define method | int Rational::height() { return (abs(num) > abs(denom)) ? abs(num) : abs(denom); } |
-(int) height { if ( abs(self.num) > abs(self.denom) ) { return abs(self.num); } return abs(self.denom); } |
public int height() { return (Math.abs(this.num) > this.denom) ? Math.abs(this.num) : this.denom; } |
public int Height() { return (System.Math.Abs(this.num) > this.denom) ? System.Math.Abs(this.num) : this.denom; } |
invoke method | r1.height(); r2->height(); |
[r1 height]; | r.height(); | r.Height(); |
define class method | declare static in class definition | precede definition with +: +(Rational*) max: (Rational*) a: (Rational*) b { if ( a.num * b.denom > b.num * a.denom ) { return a; } return b; } |
declare static in class definition | declare static in class definition |
invoke class method | ||||
name of receiver | this | self | this | this |
access control | access keywords define regions: class Foo { int privateInt1; int privateInt2; public: int publicInt1; int publicInt2; protected: int protectedInt1; int protectedInt2; private: int privateInt3; int privateInt4; }; |
access keywords define regions: @interface Foo : NSObject { int protectedInt1; int protectedInt2; @public int publicInt1; int publicInt2; @protected int protectedInt3; int protectedInt4; @private int privateInt1; int privateInt2; } @end |
access keywords required for methods and members: public class Foo { private int privateInt; protected int protectedInt; public int publicInt; } |
access keywords available for methods and members: public class Foo { private int privateInt1; int privateInt2; protected int protectedInt; public int publicInt; } |
anonymous class | possible but not useful | none | (new Object() { public void hello() { System.out.println("hello!"); } }).hello(); | |
inheritance and polymorphism | ||||
c++ | objective c | java | c# | |
dynamic dispatch | declare as virtual in base class | dispatch always dynamic | dispatch dynamic by default | declare as virtual in base class and override in derived class |
static dispatch | dispatch static by default | dispatch always dynamic | declare as final, private, or static (i.e. make it a class method) | dispatch static by default; compiler error if same method defined in base and derived class and not marked virtual in base class |
subclass | class Integer : public Rational { public: Integer(int n); virtual ~Integer(); }; |
public class RInteger extends Rational { public RInteger(int n) throws Throwable { super(n, 1); } } |
||
invoking superclass constructor | Integer::Integer(int n) : Rational(n, 1) { } |
super(n, 1); | ||
mark class underivable or method unoverrideable | none | none | final | sealed |
root class |
none | NSObject | java.lang.Object | System.Object |
root class methods | none | autorelease class conformsToProtocol: hash isEqual: isKindOfClass: isProxy performSelector: performSelector:withObject: performSelector:withObject:withObject: release respondsToSelector: retain retainCount self superclass |
clone() equals() finalize() getClass() hashCode() toString() |
Equals() Finalize() GetHashCode() GetType() MemberwiseClone() ReferenceEquals() ToString() |
reflection | ||||
c++ | objective c | java | c# | |
get type class of object | o = new Object(); Class c = o.getClass(); |
object o = new object(); System.Type t = o.GetType(); or System.type t = typeof(o); |
||
get type class from string | Class c = Class.forName("java.io.File"); | using System; Type t = Type.GetType("object"); |
||
get type class from type identifier | typeid(Foo) | System.Type t = typeof(object); | ||
class name |
typeid(Foo).name() | String name = c.getName(); | t.ToString(); | |
get methods | import java.lang.reflect.*; Method[] m = c.getMethods(); |
using System.Reflection; System.Type t = typeof(object); MethodInfo[] a = t.GetMethods(); |
||
has method | import java.lang.reflect.*; Class c = Class.forName("java.io.File"); Method[] a = c.getMethods(); boolean hasMethod = false; for (int i=0; i < a.length; i++) { if (a[i].getName() == "toString") { hasMethod = true; } } |
null if method not found: MethodInfo m = t.GetMethod("ToString"); |
||
invoke method object | import java.lang.reflect.*; Class c = Class.forName("java.io.File"); Method m = c.getMethod("toString"); Object o = new Object(); m.invoke(o); |
m.Invoke(o); | ||
net and web | ||||
c++ | objective c | java | c# | |
get local hostname, dns lookup, reverse dns lookup | ||||
http get | ||||
http post | ||||
absolute url | ||||
parse url | ||||
url encode/decode | import java.net.URLEncoder; import java.net.URLDecoder; String url = "http://www.google.com"; String s = URLEncoder.encode(url, "utf8"); String s2 = URLDecoder.decode(s, "utf8"); |
|||
base64 encode/decode | ||||
unit tests | ||||
c++ | objective c | java | c# | |
test class | $ cat > test_foo.cpp #include <cppunit/TestCaller.h> #include <cppunit/TestCase.h> #include <cppunit/TestSuite.h> #include "test_foo.h" using namespace CppUnit; void TestFoo::test_01() { CPPUNIT_ASSERT_EQUAL(1, 1); } Test* TestFoo::suite() { TestSuite* suiteOfTests = new TestSuite("Foo"); suiteOfTests->addTest( new TestCaller<TestFoo>( "test_01", &TestFoo::test_01)); return suiteOfTests; } $ cat > test_foo.h #include <cppunit/TestCase.h> class TestFoo: public CppUnit::TestCase { public: void test_01(); static CppUnit::Test* suite(); }; |
|||
run all tests | $ cat > test_runner.cpp #include <cppunit/ui/text/TestRunner.h> #include "test_foo.h" int main( int argc, char** argv) { CppUnit::TextUi::TestRunner runner; runner.addTest(TestFoo::suite()); runner.run(); return 0; } $ sudo apt-get install libcppunit-dev $ cat > Makefile test_runner: test_runner.o test_foo.o g++ -o $@ $^ -lcppunit check: test_runner ./test_runner $ make check |
|||
equality assertion | #include <cppunit/TestCase.h> CPPUNIT_ASSERT_EQUAL(1, 1); CPPUNIT_ASSERT_EQUAL("foo", "bar"); CPPUNIT_ASSERT_EQUAL_MESSAGE("1 != 1", 1, 1); |
|||
approximate assertion | ||||
exception assertion | ||||
setup | ||||
teardown | ||||
debugging and profiling | ||||
c++ | objective c | java | c# | |
flag for stronger warnings | $ g++ -Wall foo.cpp | |||
suppress warnings | $ g++ -w foo.cpp | |||
treat warnings as errors | $ g++ -Werror foo.cpp | |||
run debugger | $ g++ -g -o foo foo.cpp $ gdb foo (gdb) b main (gdb) run |
|||
debugger commands help, list source, (re)load executable, next, step, set breakpoint, show breakpoints, delete breakpoint, continue, backtrace, up stack, down stack, print, run, quit |
> h > l [FIRST_LINENO, LAST_LINENO] > file PATH > n > s > b [FILE:]LINENO > i > d NUM > c > bt > up > do > p EXPR > r [ARG1[, [ARG2 ...]] > q |
|||
benchmark code | ||||
profile code | gprof does not work on Mac OS X: $ g++ -pg -o foo foo.cpp $ ./foo $ gprof foo |
|||
memory tool | $ sudo apt-get install valgrind $ g++ -o foo foo.cpp $ valgrind ./foo |
|||
_______________________________________________ | _______________________________________________ | _______________________________________________ | _______________________________________________ |
Version
version used
The compiler version used for this sheet.
show version
How to get the compiler version.
implicit prologue
Code which examples in the sheet assume to have already been executed.
Grammar and Execution
hello world
How to write, compile, and run a "Hello, World!" program.
file suffixes
For source files, header files, and compiled object files.
C++
The gcc compiler will treat a file with any of the following suffixes as C++ source:
.cc .cp .cxx .cpp .CPP .c++ .C
GNU make has built-in rules which treat the following suffixes as C++ source:
.cc .C .cpp
The Google C++ Style Guide recommends that .cc be used as the suffix for C++ source files. Visual Studio uses .cpp as the C++ source file suffix.
One sometimes sees suffixes for headers which distinguish C++ code from C code, but the Google C++ Style Guide and Visual Studio both use .h as the C++ header suffix.
The C++11 standard library uses no suffix at all in headers, at least in the #include statements. This change was made so that the new and the old standard library headers could be distributed together and new headers could have the same basename as the old headers.
block delimiters
How blocks are delimited.
A block contains a sequence of statements. Blocks for function bodies in function definitions; to define the branches of if statements and the bodies of while loops.
Class definition bodies are blocks, though the statements that appear in them are restricted to declarations and definitions.
Bare blocks can be used to limit the scope of variables which are declared inside them.
statement terminator
How statements are terminated.
top level statements
Statements that can appear at the top level of a source file.
end-of-line comment
The syntax for a comment which is terminated by the end of the line.
multiple line comment
The syntax for a comment which can span multiple lines.
The /* */ delimiters do not nest. Using them to comment out code which already contains a /* */ comment usually results in a syntax error.
Variables and Expressions
local variable
How to declare a variable which is allocated on the stack.
uninitialized local variable
The value contained by a local variable that wasn't initialized.
global variable
How to declare a global variable.
uninitialized global variable
The value assigned to an uninitialized global variable.
write-once variable
How to declare a constant variable.
assignment
How to assign a value to a variable.
compound assignment
The compound assignment operators.
If <OP> is a binary operator and the language has the compound assignment operator <OP>=, then the following are equivalent:
x <OP>= y
x = x <OP> y
increment and decrement
The C-style increment and decrement operators.
There are prefix (preincrement and predecrement) and postfix (postincrement and postdecrement) versions. The prefix version returns the value after mutation, and the postfix version returns the value before mutation.
c++
Since the compound assignment operators also return the value after mutation, the following are equivalent for primitive types:
cout << ++i << endl;
cout << (i += 1) << endl;
The parens are necessary because compound assignment has lower precedence than the << operator.
The caveat about primitive types is necessary because the ++ operator can be overloaded. In fact the prefix and postfix versions can be overloaded separately.
In the case of the the postfix operator, the following are equivalent for primitive types:
cout << i-- << endl;
cout << (i += 1, i - 1) << endl;
The compiler may have to allocate a temporary variable to hold the value of i - 1, which means the postfix version might be slower.
address
How to get the memory address for a variable. Memory addresses are stored in a type which records the type of the variable whose address was taken.
dereference
How to get the value stored at a memory address.
type size
How to get the size of a type in bytes.
allocate heap
How to allocate memory for a primitive type on the heap.
C++
new and delete can be used to manage the memory of both primitive types and objects.
objective c
Object C has a different memory management schemes for primitive types and objects. Objects are allocated with alloc and freed by means of NSAutoreleasePool. For primitive types the same techniques are used as for C. However, idiomatic Objective C will declare primitive types as local variables or as part of the state of an object and avoid explicit calls to malloc.
Arrays of objects can be created with NSArray and NSMutableArray.
java
In Java, arrays are always stored on the heap and the JVM is responsible for garbage collection. The primitive types are stored (1) on the local frame, (2) as part of the state of an object, or (3) as part of the state of a class. The primitive types are never stored in the heap directly and when they are part of object state they are garbage collected with the object. Primitive types are passed by value unless they are encapsulated in an object.
Each of the primitive types has a wrapper class, and instantiating this class is the best approximation in Java to allocating the primitive type on the heap:
Integer i = new Integer(0);
The compiler may instantiate the wrapper class implicitly; this is called boxing. The compiler also permits use of a wrapper class in the place of the primitive type, or unboxing.
C#
C# behavior is like Java. Note that C# lacks specific wrapper classes for each primitive data type.
free heap
How to free the memory for a primitive type that was allocated on the heap.
null
C++
A typical definition:
const int NULL = 0;
coalesce
The equivalent of the COALESCE function from SQL.
C++, Objective C++:
The short circuit or operator || can be used as a coalesce operator. However, in C++ and Objective C, NULL is identical to zero, whereas in databases they are two distinct values.
Java:
The ternary operator provides the closest approximation to COALESCE, but it does not have the same behavior if the tested value has a side effect.
Arithmetic and Logic
boolean type
C
The following definitions are common:
typedef int BOOL;
#define TRUE 1
#define FALSE 0
Objective C
From objc.h:
typedef signed char BOOL;
#define YES (BOOL)1
#define NO (BOOL)0
C#
bool is an alias for System.Boolean
true and false
Literals for the boolean values true and false.
C
The following definitions are common:
typedef int BOOL;
#define TRUE 1
#define FALSE 0
Objective C
From objc.h:
typedef signed char BOOL;
#define YES (BOOL)1
#define NO (BOOL)0
falsehoods
Values which evaluate as false in the conditional expression of an if statement.
logical operators
The logical operators.
In all languages on this sheet the && and || operators short circuit: i.e. && will not evaluate the 2nd argument if the 1st argument is false, and || will not evaluate the 2nd argument if the 1st argument is true. If the 2nd argument is not evaluated, side-effects that it contains are not executed.
C++
C++ defines and, or, and not to be synonyms of &&, ||, and !, with the same semantics and precedence.
Java
The arguments of the logical operators must be of type boolean.
C#
The arguments of the logical operators must be of type bool.
relational operators
Binary operators which return boolean values.
integer type
Signed integer types.
C++
Whether char is a signed or unsigned type depends on the implementation.
C#
C# has the following aliases:
sbyte: System.SByte
short: System.Int16
int: System.Int32
long: System.Int64
unsigned type
Unsigned integer types.
C++
Whether char is a signed or unsigned type depends on the implementation.
C#
C# has the following aliases:
byte: System.Byte
ushort: System.UInt16
uint: System.UInt32
ulong: System.UInt64
float type
Floating point types.
C#
C# has the following aliases:
float: System.Single
double: System.Double
fixed type
Fixed-point decimal types.
C#:
C# has the following alias:
decimal: System.Decimal
arithmetic operators
The arithmetic binary operators: addition, subtraction, multiplication, division, modulus.
integer division
How to get the quotient of two integers.
integer division by zero
The results of integer division by zero.
C++, Objective C
The behavior for division by zero is system dependent; the behavior described is nearly universal on Unix.
C#
It is a compilation error to divide by a zero constant. Division by a variable set to zero results in a runtime exception.
float division
How to perform floating point division on two integers.
float division by zero
The result of floating point division by zero.
Modern hardware, if it implements floating point instructions, will implement instructions which conform to the IEEE 754 standard. The standard requires values for positive infinity, negative infinity, and not-a-number (NaN).
The C and C++ standards do not assume that they are running on hardware which provides these values; code which assumes they exist is not strictly speaking portable.
power
How to perform exponentiation.
C++
powm1 is an abbreviation for "power minus one". Hence the need to add one to get the answer.
sqrt
The positive square root function.
sqrt -1
The result of taking the square root of a negative number.
Here is a list of the standard mathematical functions whose domains do not cover the entire real number line:
function | returns inf on | returns nan on | returns -inf on |
---|---|---|---|
sqrt | inf | [-inf, 0) | |
log | inf | [-inf, 0) | 0 |
asin | [-inf, -1) U (1, inf] | ||
acos | [-inf, -1) U (1, inf] |
transcendental functions
The exponential and logarithm functions; the trigonometric functions; the inverse trigonometric functions.
The arguments of the trigonometric functions are in radians as are the return values of the inverse trigonometric functions.
transcendental constants
The transcendental constants e and pi.
float truncation
Functions for converting a float to a nearby integer value.
C:
The math.h library also provides floor and ceil which return double values.
Java:
Math.floor and Math.ceil return double values.
absolute value
The absolute value of a numeric quantity.
integer overflow
What happens when an integer expression results in a value larger than what can be stored in the integer type.
float overflow
What happens when a float expression results in a value larger than largest representable finite float value.
float limits
The largest finite floating point number and the smallest positive floating point number.
complex construction
How to construct a complex number.
complex decomposition
How to get the components of a complex number. Both Cartesian and polar decompositions are illustrated. Also how to get the complex conjugate.
random number
Ways to generate random numbers. The distributions are a uniform integer from 0 to 99; a uniform float from 0.0 to 1.0; a standard normal float.
c++:
The standard library includes functions for generating random numbers from other distributions.
random seed
How to set the seed for the random number generator.
bit operators
The bit operators: left shift, right shift, and, or, xor, and complement.
C++
bitand, bitor, and compl are synonyms of &, |, and ~ with identical precedence and semantics.
binary, octal, and hex literals
Binary, octal, and hex integer literals.
radix
How to convert integers to strings of digits of a given base. How to convert such strings into integers.
Strings
string type
The type for strings.
string literal
The syntax for string literals.
newline in literal
Can a newline be used in a string literal? Does the newline appear in the resulting string object?
literal escapes
Escape sequences that can be used in string literals.
allocate string
How to allocate a string.
Java
The following code
String t = new String(s);
creates a copy of the string s. However, because Java strings are immutable, it would be safe to store the same string object it t as follows:
String t = s;
are strings mutable?
copy string
format string
compare strings
C++
string::compare returns a positive value, 0, or a negative value depending upon whether the receiver is lexicographically greater, equal, or less than the argument. C++ overload the comparison operators (<, >, ==, !=, <=, >=) so that they can be used for string comparison.
Objective C
compare will return -1, 0, or 1.
Java
compareTo will return a negative value, 0, or a positive value.
C#
CompareTo will return -1, 0, or 1.
concatenate
replicate
translate case
trim
pad
number to string
string to number
C++
strtoimax, strtol, strtoll, strtoumax, strtoul, and strtoull take three arguments:
intmax_t
strtoimax(const char *str, char **endp, int base);
The 2nd argument, if not NULL, will be set to first character in the string that is not part of the number. The 3rd argument can specify a base between 2 and 36.
strtof, strtod, and strtold take three arguments:
double
strtod(const char *str, char **endp);
Java
parseInt has an optional second argument for the base.
join
java:
Use StringBuilder to implement join:
public static String join(String[] a, String sep) {
StringBuilder sb = new StringBuilder();
for (int i=0; i<a.length; i++) {
if (i > 0) {
sb.append(sep);
}
sb.append(a[i]);
}
return sb.toString();
}
split
serialize
string length
index of substring
extract substring
character type
character literal
test character
Regular Expressions
regex match
regex substitute
Date and Time
date and time type
The data type used to store a combined date and time.
current date and time
How to get the current date and time.
to unix epoch, from unix epoch
How to convert a date/time object to the Unix epoch. How to convert the Unix epoch to a date/time object.
The Unix epoch is the number of seconds since 1 January 1970 UTC.
c#:
Windows file time is the number of nanoseconds since 1 January 1601 UTC divided by 100. The concept was introduced when journaling was added to NTFS with Windows 2000.
The magic constant (11644473600) used for the conversion can be calculated with the following code:
using System;
using System.Globalization;
CultureInfo enUS = new CultureInfo("en-US");
DateTime startEpoch = DateTime.ParseExact(
"1970-01-01 00:00:00 -00",
"yyyy-MM-dd HH:mm:ss zz",
enUS);
Console.WriteLine(startEpoch.ToFileTimeUtc() / (10 * 1000 * 1000));
format date
How to use a format string to display a date/time object.
The canonical example of doing this is the strftime function from the C standard library which defines used letters prefix by percent signs as conversion specification characters, e.g. %Y-%m-%d.
parse date
How to use a format string to parse date data from a string.
date subtraction
add duration
date parts
time parts
Fixed-Length Arrays
declare on stack
How to allocate an array which is freed when the block in which it is defined goes out of scope.
declare on heap
How to allocate an array on the heap.
free heap
How to free an array that was allocated on the heap.
initialization list
Objective C
NSArray can only store instances of NSObject. For primitive types, use C arrays.
Java
Java permits arrays to be declared with C-style syntax:
int a[] = {1,2,3}
size
How to get the size of a fixed-length array.
lookup
How to get the value stored at an index in a fixed-length array.
C++
Arrays can be manipulated with pointer syntax. The following sets x and y to the same value:
int a[] = {3,7,4,8,5,9,6,10};
int x = a[4];
int y = *(a+4);
update
How to update the value stored at an index in a fixed-length array.
out-of-bounds
What happens when an out-of-bounds index is used to access a value in a fixed-length array.
copy
How to copy a fixed-length array.
as function argument
How to pass a fixed-length array as a function argument.
iterate
How to iterate over the values of the fixed-length array.
C++
Range-based for loops can be used with fixed-length arrays (but not pointers):
int a[4] = {3, 2, 4, 1};
int sum(0);
for (const auto& n: a) {
sum += n;
}
sort
Resizable Arrays
declare
initialization list
size
capacity
empty test
lookup
update
out-of-bounds behavior
element index
slice
slice to end
manipulate back
manipulate front
concatenate
replicate element
copy
array as function argument
iterate
How to iterate over a resizable array.
C++
The range-based for loop was introduced in C++11. It it can be used to iterate over an initialization list:
for (const auto& n: {1, 2, 3}) {
sum += n;
}
Tuples
pair
Dictionaries
map declaration
C:
For those interested in an industrial strength hashtable implementation for C, here is the header file and the source file for the hashtable used by Ruby.
For those interested in a "Computer Science 101" implementation of a hashtable, here is a simpler source file and header file.
map access
map size
map remove
map element not found result
map iterator
Functions
declare function
How to declare the type of a function.
define function
How to define a function.
invoke function
How to invoke a function.
define static class method
invoke static class method
overload function
default argument
variable number of arguments
named parameters
Objective C:
Named parameters must be invoked in the order in which they are defined in the method signature.
C#:
Named parameter do not need to be invoked in the order in which they are defined in the method signature. Additionally, their use in
invocation is optional: the arguments can be provided without names in which case the definition order must be used.
pass by value
pass by reference
pass by address
return value
no return value
recursive function
anonymous function
invoke anonymous function
closure
function with private state
function as value
overload operator
C++
A note on how to overload postfix and prefix ++ and —.
Execution Control
if
The syntax for an if statement.
dangling else
The curly braces around the branches of an if statement are optional when the branch contains a single statement.
From the perspective of the parser, the branches are statements. Curly branch delimited blocks are legal wherever a statement is legal.
When if statements are nested and the outer if statement does not put its if-clause in curly braces, the parser will match a subsequent else to the inner if. Code which puts the else on the same level of indentation as the outer if is deceptive.
switch
The syntax for a switch statement.
A switch checks the value of integer expression and jumps to the correct label. This can faster than an if statement with numerous else if branches which tests the expression until a match is found.
Execution falls through to code after subsequent labels unless a break statement is encountered. This makes it possible to write code once which handles multiple values.
while
The syntax for a while loop.
If the body of a while loop is a single statement, the curly braces are optional.
The languages in this sheet also have a do-while loop, which is a loop which always executes at least once.
Here is an example of a do-while loop which converts an unsigned integer to a string. The corresponding while loop would require extra handling when the integer is zero.
/* unsigned int n;
* char* s;
*/
do {
s[i++] = n % 10 + '0';
} while ((n /= 10) > 0);
s[i] = '\0';
reverse(s);
for
The syntax for a C-style for loop.
The parens of the for loop contain three expressions set off by semicolons: the initialization, the condition, and the increment.
The initialization expression executes once before the loop starts.
The condition expression executes once before the start of each iteration. The loop stops if the condition is false.
The increment executes at the end of each iteration.
break
The break statement terminates execution of the innermost containing loop or switch statement.
break out of nested loops
A method for breaking out of nested loops.
continue
The continue statement, which terminates execution of the current loop iteration.
goto
Exceptions
base exception
The base class or interface for exceptions.
predefined exceptions
A partial list of exceptions raised by the language or the standard library.
raise exception
How to raise an exception.
C++
C++ code can throw or catch any type of object or primitive data type. The C++ standard library throws subclasses of std::exception, which does not have a message member.
Objective C
Objective C can only throw an instance of NSException or one of its subclasses.
Java
Java can only throw an implementation of java.lang.Throwable.
C#
C# can only throw an instance of System.Exception of one of its subclasses.
handle exception
How to handle an exception.
C++
Exceptions can be caught by value or by reference. If the exception is an object and it is caught by value, the copy constructor and the destructor will be invoked.
Objective C
Exceptions are thrown and caught by pointer value.
define exception
How to define a new exception type.
re-raise exception
How to handle and re-raise an exception.
catch-all handler
How to write a handler witch catches any exception.
multiple handlers
error message
system call errno
finally clause
C++
Class Finally {
void (*finally)();
Finally(void (*f)()) : finally(f) {
}
~Finally() {
do_cleanup();
}
};
{
Cleanup c();
risky();
}
exception specification
Java
If a method throws a subclass of java.lang.Exception, it must declare the exception in its throws clause. This includes exceptions originating in code called by the method. On the other hand, if the method throws a subclass of java.lang.Error, no declaration in the throws clause is necessary.
Concurrency
File Handles
printf
How to print a formatted string to standard out.
read from file
C
If there is an error, the global variable errno will be set to a nonzero value, and strerror(errno) will return an error message for the error.
write to file
Files
File Formats
Directories
Processes and Environment
signature of main
first argument
C
The first argument is the pathname to the executable. Whether the pathname is absolute or relative depends on how the executable was invoked. If the executable was invoked via a symlink, then the first argument is the pathname of the symlink, not the executable the symlink points to.
environment variable
iterate through environment variables
Library and Namespaces
standard library name
The name of the standard library.
C++
Standard Template Library (STL)
The STL might not be installed by default.
Objective C
The Foundation Framework is the core of Cocoa, a set of libraries for Objective C development on Mac OS X and the iPhone. The Foundation Framework descends from NextStep, hence the NS prefix in the class names. NextStep was made available to operating systems other than Next as OpenStep and the GNU implementation is called GNUStep.
Java
C#
.NET Framework 4 Class Library
Mono Documentation
The core of the .NET framework is called the Base Class Library. Mono implements the BCL, but not all of the .NET framework.
User-Defined Types
typedef
C
Because C integer types don't have well defined sizes, typedef is sometimes employed to as an aid to writing portable code. One might include the following in a header file:
typedef int int32_t;
The rest of the code would declare integers that need to be 32 bits in size using int32_t and if the code needed to be ported to a platform with a 16 bit int, only a single place in the code requires change. In practice the typedef abstraction is leaky because functions in the standard library such as atoi, strtol, or the format strings used by printf depend on the underlying type used.
Java
Java has well defined integer sizes so typedef is not needed as a portability aid. In other situations where a C programmer would use a typedef for data abstraction, a Java programmer must either define a class or retain the raw primitive type throughout the code.
enum
C
Enums were added to the C standard when the language was standardized by ANSI in 1989.
An enum defines a family of integer constants. If an integer value is not explicitly provided for a constant, it is given a value one greater than the previous constant in the list. If the first constant in the list is not given an explicit value, it is assigned a value of zero. it is possible for constants in a list to share values. For example, in the following enum, a and c are both zero and b and d are both one.
enum { a=0, b, c=0, d };
A typedef can be used to make the enum keyword unnecessary in variable declarations:
typedef enum { mon, tue, wed, thu, fri, sat, sun } day_of_week;
day_of_week d = tue;
From the point of view of the C compiler, an enum is an int. The C compiler does not prevent assigning values to an enum type that are not in the enumerated list. Thus, the following code compiles:
enum day_of_week { mon, tue, wed, thu, fri, sat, sun };
day_of_week d = 10;
typedef enum { mon, tue, wed, thu, fri, sat, sun } day_of_week2;
day_of_week2 d2 = 10;
C++
C++ enums are more strongly typed the C enums. The compiler rejects attempts to assign a value to an enum variable that is not in the enumerated list. The following code:
enum day_of_week { mon, tue, wed, thu, fri, sat, sun };
day_of_week d = 10;
produces an error like the following:
main.cpp: In function ‘int main()’:
main.cpp:21: error: invalid conversion from ‘int’ to ‘main()::day_of_week’
Java
Java added enums in 1.5.
Java enums are strongly typed like C++ enums. Unlike C++ enums, it is an error to use an enum value in an integer context. The value has a method ordinal() which returns the integer value, however.
When used in a string context, an enum will evaluate as the string corresponding to its identifier: i.e. "TUE" for DayOfWeek.TUE. This string can be accessed explicitly with DayOfWeek.TUE.toString(). Conversely, DayOfWeek.valueOf("TUE") returns DayofWeek.TUE.
Java enums are subclasses of java.lang.Enum. In particular, an enum is a class, and if the last value if the enum definition is followed by a semicolon, what follows is a class body which can contain methods and constructors. An enum class is final and cannot be subclassed, but an enum can implement an interface.
C#
Like Java enums, C# enums will return the string corresponding to their identifier. Unlike Java enums, C# enums will evaluate as integers in a numeric context.
When used as an argument in a C# style format string, an enum value returns the string corresponding to its identifier.
struct definition
A struct provides names for elements in a predefined set of data and permits the data to be accessed directly without the intermediation of getters and setters. C++, Java, and C# classes can be used to define structs by making the data members public. However, public data members violates the uniform access principle.
C++:
From The C++ Programming Language: 3rd Edition:
by definition, a struct is a class in which members are by default public; that is,
struct s { ...
is simply shorthand for
class s { public: ...
struct declaration
struct initialization
C
The literal format for a struct can only be used during initialization. If the member names are not provided, the values must occur in the order used in the definition.
struct member assignment
struct member access
C
The period operator used for member access has higher precedence than the pointer operator. Thus parens must be used
to get at the member of a struct referenced by a pointer:
struct medal_count {
char* country;
int gold;
int silver;
int bronze;
}
struct medal_count spain = { "Spain", 3, 7 4 };
struct medal_count *winner = &spain;
printf("The winner is %s with %d gold medals", (*winner).country, (*winner).gold);
ptr->mem is a shortcut for (*ptr).mem:
printf("The winner (%s) earned %d silver medals", winner->country, winner->silver);
Generic Types
define generic type
instantiate generic type
Objects
define class
constructor
create object
destructor
C++
The C++ compiler will normally see to it that the destructor for a class and all its superclasses is called. The compiler may not be aware of the true class of the object if it was upcast to one of its base class. If the destructor was not declared virtual, then the derived class destructor and any other base class constructors will not get called. Thus many developers declare all destructors virtual.
Java
Java does not chain finalize() methods, so the derived class should explicitly call the parent.
destroy object
Java
finalize() is called by the Java garbage collector.
define method
invoke method
define class method
invoke class method
name of receiver
access control
objective c:
Access control only applies to members; all methods are public. gcc 4.0 does not enforce the access restrictions; it merely gives warnings.
anonymous class
Inheritance and Polymorphism
dynamic dispatch
static dispatch
Method dispatch is static if the method is determined by the variable type, and dynamic if it is determined by the value type. These techniques of method dispatch yield different results when both the base class and the derived class have implementations for a method, and an instance of the derived class is being stored in a variable with type of the base class.
When dispatch is static, the compiler can determine the code that will be executed for the method call. When dispatch is dynamic, the code that will be executed is a runtime decision. C++ implementations usually achieve this by storing function pointers in the object: qv virtual method table.
The use of the keyword static in the declaration of a class method in C++, Java, and C# is perhaps unfortunate. Class methods are always statically dispatched, so the concepts are not unrelated.
subclass
superclass constructor
mark class underivable or method overrideable
root class
Name of the root class, if there is one.
objective c:
It is possible to define a root class other than NSObject.
root class methods
A selection of methods available on the root class.
Reflection
get type class of object
get type class from string
get type class from type identifier
c++:
typeid returns a value of type type_info. The assignment method and copy constructor of type_info are private.
class name
*c++:**
The string returned by type_info.name() contains more than the class name. The code below displayed the string "Z4mainE3Foo" when run on my system.
class Foo {
int i;
};
puts(typeid(Foo).name());
get methods
has method
invoke method object
Net and Web
url encode/decode
How to URL encode and URL decode a string.
URL encoding is also called percent encoding. It is used to escape special characters in GET query string parameters.
Reserved characters according to RFC 3986 are replaced by a percent sign % followed by a two hex digit representation of the ASCII code. The reserved characters are:
! * ' ( ) ; : @ & = + $ , / ? # [ ]
Spaces can optionally be represented by a plus sign +.
Unit Tests
Debugging and Profiling
C++
C++11 Standard (pdf)
Standard C++ Library Reference
The GNU C++ Library
Google C++ Style Guide
Designing Qt-Style C++ APIs
C++11 and gcc
gcc provides a C++11 compiler which will run on Linux, Mac OS X, and Windows. For a complete implementation of the C++11 standard one should use gcc 4.8 or later, but gcc 4.6 is sufficient for the examples in this sheet. Support for C++11 features must be requested with the -std=c++0x flag.
C++11 on Mac OS X
The version of gcc that comes with XCode in Mac OS X 10.8 as part of the command line tools package is 4.2. This version of gcc does not support C++11, but the command line tools package also provides the clang compiler which does:
clang++ -std=c++11 -stdlib=libc++ -o hello hello.cpp
Like gcc, clang does not compile C++11 by default, hence the -std=c++11 flag. One must also specify the C++ standard library, since the libc++ library which comes with clang will support C++11, but the libstdc++ library provided with gcc 4.2 will not, and clang uses the gcc library by default.
C++11 Windows
The Visual Studio 2012 C++ compiler does not completely support C++11, but it has support for the features mentioned in this sheet. For a complete C++11 compiler, install MinGW and gcc 4.8.
Compatibility with C
What's New in C++11
Objective-C
Programming with Objective-C Apple
GNUstep
Mac OS X Foundation Framework
Java
Java 1.6 API
JDK 7 Project
JVM Specification 2nd Ed
The Java Language Specification 3rd Ed
A Java program is created from source code via an explicit compilation step using javac. The executable is then launched using the virtual machine java. Both javac and java use the Java runtime jar rt.jar, which contains the Java standard libraries.
$ ls -l $(which javac)
-rwxrwxr-x 1 root wheel 99296 Oct 8 2013 /Library/JVM/jdk7.0/Contents/Home/bin/javac
$ ls -l $(which java)
-rwxrwxr-x 1 root wheel 99216 Oct 8 2013 /Library/JVM/jdk7.0/Contents/Home/bin/java
$ ls -l $JAVA_HOME/jre/lib/rt.jar
-rw-rw-r-- 1 root wheel 64181940 Oct 8 2013 /Library/JVM/jdk7.0/Contents/Home/jre/lib/rt.jar
$ cat Main.java
public class Main {
public static void main(String[] argv) throws Throwable {
System.out.println("Hello, World!");
}
}
$ javac Main.java
$ ls -l Main.class
-rw-r--r-- 1 hpglot staff 463 Dec 27 06:12 Main.class
$ java Main
Hello, World!
Using dtruss on Mac OS X to verify that javac and java use rt.jar:
$ sudo dtruss javac Main.java 2>&1 | grep -E '^open' | grep rt.jar
open("/Library/JVM/jdk7.0/Contents/Home/jre/lib/rt.jar\0", 0x0, 0x0) = 4 0
$ sudo dtruss java Main 2>&1 | grep -E '^open' | grep rt.jar
open("/Library/JVM/jdk7.0/Contents/Home/jre/lib/rt.jar\0", 0x0, 0x0) = 4 0
C#
C# Standard: ECMA-334
Mono API
C# Programming Guide Microsoft