Skip to content

Commit 1b6e3c9

Browse files
committed
Align cpp demos with docs 51-60 (google_benchmark through lexical_analyzer)
Each cpp mirrors only what its doc covers, with short labeled demos. - src/benchmark_demo.cpp: BENCHMARK(fn) + BENCHMARK_MAIN, CustomArguments with Arg ranges, BENCHMARK_F fixture with SetUp/TearDown, DoNotOptimize + SetItemsProcessed throughput. Verified by configuring with ENABLE_BENCHMARKING=ON. - src/hash.cpp: std::hash<float|int|string> primitives, custom std::hash specialization vs KeyHasher functor on a user-defined `student`, bucket interface (bucket_count/load_factor/max_load_factor/bucket_size). - src/heap_and_stack_memory_layout_of_C_programs.cpp: print addresses for .text / .rodata / .data / .bss / heap / stack and confirm the expected ascending ordering. Replaces a 4-line empty-main stub. - Create src/immutable_objects.cpp: ImmutablePoint with const members, deleted operator=, and a movedBy(dx,dy) const that returns a new copy. - src/initialization.cpp: 10 sections mapping 1:1 to the doc (default-init, value-init, direct-init, copy-init, list-init, aggregate, zero-init, in-class member init, narrowing, std::initializer_list ctor) plus the declaration-order trap and a most-vexing-parse comment. - src/iterator_loop.cpp: input/output/forward/bidirectional/random-access iterators, iterator_traits + category tag dispatch, minimal custom SampleBuffer iterator, range-based for variants, cbegin loop, next/advance/distance. - src/json_example.cpp: 11 nlohmann/json sections from literals, parse, dump, [] vs at, iteration, STL interop, exception types, json::array, type checks, merge_patch, file I/O to /tmp. - src/lambda.cpp: inline + stored lambda, file-scope lambda used with std::for_each, [=] mutable vs [&] vs mixed [=, &y], template + std::function acceptors. Removed topics the doc doesn't cover. - Create src/lexical_analyzer.cpp: ~80-line hand-rolled lexer that tokenizes the doc's exact example snippet (keywords / identifiers / literals / scope_op :: / insertion_op << / punctuation). - CMakeLists: add immutable_objects + lexical_analyzer executables. - Skipped godbolt.md (meta-doc about Compiler Explorer).
1 parent c47e1b0 commit 1b6e3c9

10 files changed

Lines changed: 894 additions & 376 deletions

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ add_executable(unions src/unions.cpp)
9797
add_executable(basic_IO_operation_streams src/basic_IO_operation_filesystem_streams_reading_writing_files_formating_output_cin_cout_scanf_printf_gets_puts_getline.cpp)
9898
add_executable(filesystem src/filesystem.cpp)
9999
add_executable(const_constexpr_mutable src/const_constexpr_mutable.cpp)
100+
add_executable(immutable_objects src/immutable_objects.cpp)
100101
add_executable(literals src/literals.cpp)
101102
add_executable(ternary src/ternary.cpp)
102103
add_executable(lists src/lists.cpp)
@@ -125,6 +126,7 @@ add_executable(memory_checking src/memory_checking.cpp)
125126
add_executable(tricky_questions src/tricky_questions.cpp)
126127
add_executable(metaprogramming src/metaprogramming.cpp)
127128
add_executable(regex_mathch_search src/regex_mathch_search.cpp)
129+
add_executable(lexical_analyzer src/lexical_analyzer.cpp)
128130
add_executable(optional src/optional.cpp)
129131
add_executable(std_invoke src/std_invoke.cpp)
130132
add_executable(structured_binding_declaration src/structured_binding_declaration.cpp)

src/benchmark_demo.cpp

Lines changed: 52 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,58 @@
1-
// https://www.youtube.com/watch?v=eKODykkIZTE&t=108s
1+
// Educational examples for Google Benchmark.
2+
// Mirrors docs/google_benchmark.md.
3+
24
#include <benchmark/benchmark.h>
5+
#include <string>
6+
#include <vector>
7+
8+
// Example 1: Benchmarking a simple function.
9+
// The for-range loop is executed many times by the framework.
10+
static void StringCreation(benchmark::State& state) {
11+
for (auto _ : state) {
12+
std::string s("Hello, World!");
13+
}
14+
}
15+
BENCHMARK(StringCreation);
316

4-
static void BM_StringCreation(benchmark::State &state) {
5-
for (auto _ : state)
6-
std::string empty_string;
17+
// Example 2: Benchmarking with custom arguments.
18+
// state.range(0) returns the value supplied via ->Arg(...).
19+
static void CustomArguments(benchmark::State& state) {
20+
int n = state.range(0);
21+
for (auto _ : state) {
22+
std::vector<int> v(n);
23+
}
724
}
8-
// Register the function as a benchmark
9-
BENCHMARK(BM_StringCreation);
10-
11-
// Define another benchmark
12-
static void BM_StringCopy(benchmark::State &state) {
13-
std::string x = "hello";
14-
for (auto _ : state)
15-
std::string copy(x);
25+
BENCHMARK(CustomArguments)->Arg(1024)->Arg(2048)->Arg(4096);
26+
27+
// Example 3: Using fixtures for setup and teardown.
28+
class MyBenchmarkFixture : public benchmark::Fixture {
29+
public:
30+
void SetUp(const ::benchmark::State& state) override {
31+
// Code to set up before each benchmark iteration.
32+
}
33+
34+
void TearDown(const ::benchmark::State& state) override {
35+
// Code to clean up after each benchmark iteration.
36+
}
37+
};
38+
39+
BENCHMARK_F(MyBenchmarkFixture, ExampleBenchmark)(benchmark::State& state) {
40+
for (auto _ : state) {
41+
// Benchmark code.
42+
}
43+
}
44+
45+
// Example 4: Measuring throughput.
46+
// DoNotOptimize prevents the compiler from removing unused work.
47+
// SetItemsProcessed lets the report show items/second.
48+
static int some_operation() { return 42; }
49+
50+
static void BM_Throughput(benchmark::State& state) {
51+
for (auto _ : state) {
52+
benchmark::DoNotOptimize(some_operation());
53+
}
54+
state.SetItemsProcessed(state.iterations());
1655
}
17-
BENCHMARK(BM_StringCopy);
56+
BENCHMARK(BM_Throughput);
1857

1958
BENCHMARK_MAIN();

src/hash.cpp

Lines changed: 48 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,123 +1,102 @@
1+
// Hash functions and hash-based containers.
2+
// Follows docs/hash_function_hash_table.md.
3+
14
#include <iostream>
2-
#include <set>
35
#include <string>
46
#include <unordered_map>
57
#include <unordered_set>
68

7-
// user-defined hash functions:
8-
// Example 1
9-
10-
class Course {
11-
public:
12-
std::string m_name;
13-
bool m_isAdvanced;
14-
15-
Course(std::string name, bool isAdvanced) {
16-
m_name = name;
17-
m_isAdvanced = isAdvanced;
18-
}
19-
20-
bool isAdvanced() { return m_isAdvanced; }
9+
// ----- std::hash on built-in types ---------------------------------------
10+
void builtinHash() {
11+
std::cout << "--- std::hash on primitives and strings ---\n";
2112

22-
bool operator==(const Course &rhs) const {
23-
return ((rhs.m_isAdvanced == this->m_isAdvanced) &&
24-
(rhs.m_name == this->m_name));
25-
}
26-
};
27-
28-
class CourseHashFunction {
29-
public:
30-
std::size_t operator()(const Course &k) const {
31-
// We use predfined hash functions of string and bool and define our hash
32-
// function as XOR of the hash values.
33-
return (std::hash<std::string>()(k.m_name)) ^
34-
(std::hash<bool>()(k.m_isAdvanced));
35-
}
36-
};
13+
std::hash<float> float_hasher;
14+
std::hash<int> int_hasher;
15+
std::hash<std::string> str_hasher;
3716

38-
// Example 2
17+
std::cout << "hash(3.14f) = " << float_hasher(3.14f) << "\n";
18+
std::cout << "hash(42) = " << int_hasher(42) << "\n";
19+
std::cout << "hash(\"hello\") = " << str_hasher("hello") << "\n";
20+
}
3921

22+
// ----- User-defined type + std::hash specialization ----------------------
4023
class student {
4124
public:
4225
int id;
4326
std::string first_name;
4427
std::string last_name;
4528

4629
bool operator==(const student &other) const {
47-
return (first_name == other.first_name && last_name == other.last_name &&
48-
id == other.id);
30+
return first_name == other.first_name && last_name == other.last_name &&
31+
id == other.id;
4932
}
5033
};
5134

35+
// Specialization inside std:: lets unordered_map<student, V> work directly.
5236
namespace std {
53-
5437
template <> struct hash<student> {
5538
std::size_t operator()(const student &k) const {
56-
57-
// Compute individual hash values for first,
58-
// second and third and combine them using XOR
59-
// and bit shifting:
60-
39+
// Combine field hashes with XOR and bit shifts.
6140
return ((std::hash<string>()(k.first_name) ^
6241
(std::hash<string>()(k.last_name) << 1)) >>
6342
1) ^
6443
(std::hash<int>()(k.id) << 1);
65-
;
6644
}
6745
};
68-
6946
} // namespace std
70-
// If you don't want to specialize template inside the std namespace (although
71-
// it's perfectly legal in this case), you can define the hash function as a
72-
// separate class and add it to the template argument list for the map:
7347

48+
// Alternative: a standalone hasher passed as a template argument.
7449
struct KeyHasher {
7550
std::size_t operator()(const student &k) const {
76-
7751
return ((std::hash<std::string>()(k.first_name) ^
7852
(std::hash<std::string>()(k.last_name) << 1)) >>
7953
1) ^
8054
(std::hash<int>()(k.id) << 1);
8155
}
8256
};
8357

84-
void unordered_mapCustomClasstype() {
58+
void userDefinedHash() {
59+
std::cout << "--- user-defined hash for a class ---\n";
60+
61+
// Uses std::hash<student> specialization.
8562
std::unordered_map<student, std::string> student_umap = {
8663
{{1, "John", "Doe"}, "example"}, {{2, "Mary", "Sue"}, "another"}};
8764

88-
std::unordered_map<student, std::string, KeyHasher> m6 = {
65+
// Uses KeyHasher passed as the third template argument.
66+
std::unordered_map<student, std::string, KeyHasher> student_umap2 = {
8967
{{1, "John", "Doe"}, "example"}, {{2, "Mary", "Sue"}, "another"}};
68+
69+
std::cout << "student_umap size = " << student_umap.size() << "\n";
70+
std::cout << "student_umap2 size = " << student_umap2.size() << "\n";
9071
}
9172

92-
void sizeOfTheHashTable() {
93-
// Example with std::unordered_map
73+
// ----- Bucket interface --------------------------------------------------
74+
void bucketInterface() {
75+
std::cout << "--- bucket_count / load_factor / max_load_factor ---\n";
76+
9477
std::unordered_map<int, std::string> my_map = {
9578
{1, "one"}, {2, "two"}, {3, "three"}};
9679

97-
std::cout << "Number of buckets in my_map: " << my_map.bucket_count()
98-
<< std::endl;
99-
std::cout << "Current load factor in my_map: " << my_map.load_factor()
100-
<< std::endl;
101-
std::cout << "Max load factor in my_map: " << my_map.max_load_factor()
102-
<< std::endl;
80+
std::cout << "my_map bucket_count = " << my_map.bucket_count() << "\n";
81+
std::cout << "my_map load_factor = " << my_map.load_factor() << "\n";
82+
std::cout << "my_map max_load_factor = " << my_map.max_load_factor() << "\n";
10383

104-
// Example with std::unordered_set
10584
std::unordered_set<int> my_set = {1, 2, 3, 4, 5};
10685

107-
std::cout << "Number of buckets in my_set: " << my_set.bucket_count()
108-
<< std::endl;
109-
std::cout << "Current load factor in my_set: " << my_set.load_factor()
110-
<< std::endl;
111-
std::cout << "Max load factor in my_set: " << my_set.max_load_factor()
112-
<< std::endl;
113-
114-
// Accessing the size of a specific bucket
115-
size_t bucket_index = 0;
116-
std::cout << "Elements in bucket " << bucket_index
117-
<< " of my_map: " << my_map.bucket_size(bucket_index) << std::endl;
86+
std::cout << "my_set bucket_count = " << my_set.bucket_count() << "\n";
87+
std::cout << "my_set load_factor = " << my_set.load_factor() << "\n";
88+
std::cout << "my_set max_load_factor = " << my_set.max_load_factor() << "\n";
89+
90+
// Size of a specific bucket.
91+
std::size_t bucket_index = 0;
92+
std::cout << "my_map bucket_size(" << bucket_index
93+
<< ") = " << my_map.bucket_size(bucket_index) << "\n";
11894
}
11995

12096
int main() {
121-
unordered_mapCustomClasstype();
122-
sizeOfTheHashTable();
97+
builtinHash();
98+
std::cout << "\n";
99+
userDefinedHash();
100+
std::cout << "\n";
101+
bucketInterface();
123102
}
Lines changed: 88 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,89 @@
1-
static int global_static = 1;
2-
int global_var = 1;
1+
// Memory layout demo: print the address of one variable from each segment
2+
// and observe where each lives in the process's virtual address space.
3+
//
4+
// high address
5+
// stack (locals, grows down)
6+
// heap (new/malloc, grows up)
7+
// .bss (zero-initialized globals/statics)
8+
// .data (nonzero-initialized globals/statics)
9+
// .rodata (string literals, const tables)
10+
// .text (code)
11+
// low address
312

4-
int main(void) { static int local_static = 1; }
13+
#include <cstdio>
14+
15+
// .data : nonzero-initialized global
16+
int global_initialized = 1;
17+
static int static_initialized = 1;
18+
19+
// .bss : zero-initialized global
20+
int global_uninitialized;
21+
static int static_uninitialized;
22+
23+
// .rodata : a const table the compiler can put in read-only memory
24+
const char rodata_string[] = "behnam";
25+
26+
// .text : a function lives in code
27+
void some_function() {}
28+
29+
void show_text_segment() {
30+
printf("[.text] address of some_function : %p\n",
31+
(void*)&some_function);
32+
}
33+
34+
void show_rodata_segment() {
35+
printf("[.rodata] address of rodata_string : %p\n",
36+
(void*)rodata_string);
37+
}
38+
39+
void show_data_segment() {
40+
printf("[.data] address of global_initialized: %p\n",
41+
(void*)&global_initialized);
42+
printf("[.data] address of static_initialized: %p\n",
43+
(void*)&static_initialized);
44+
}
45+
46+
void show_bss_segment() {
47+
printf("[.bss] address of global_uninit : %p\n",
48+
(void*)&global_uninitialized);
49+
printf("[.bss] address of static_uninit : %p\n",
50+
(void*)&static_uninitialized);
51+
}
52+
53+
void show_heap() {
54+
int* p = new int(42);
55+
printf("[heap] address from new int : %p\n", (void*)p);
56+
delete p;
57+
}
58+
59+
void show_stack() {
60+
int local_a = 0;
61+
int local_b = 0;
62+
printf("[stack] address of local_a : %p\n", (void*)&local_a);
63+
printf("[stack] address of local_b : %p\n", (void*)&local_b);
64+
// On x86-64 the stack grows down, so &local_b is typically lower than &local_a.
65+
}
66+
67+
int main() {
68+
printf("=== .text (code) ===\n");
69+
show_text_segment();
70+
71+
printf("\n=== .rodata (read-only data) ===\n");
72+
show_rodata_segment();
73+
74+
printf("\n=== .data (initialized globals/statics) ===\n");
75+
show_data_segment();
76+
77+
printf("\n=== .bss (zero-initialized globals/statics) ===\n");
78+
show_bss_segment();
79+
80+
printf("\n=== heap (new / malloc) ===\n");
81+
show_heap();
82+
83+
printf("\n=== stack (locals) ===\n");
84+
show_stack();
85+
86+
printf("\nExpected ordering (low -> high addresses):\n");
87+
printf(" .text < .rodata < .data < .bss < heap << stack\n");
88+
return 0;
89+
}

0 commit comments

Comments
 (0)