WEBVTT

1
00:00:00.080 --> 00:00:04.120
<v Speaker 1>Imagine cutting through the noise of a dense C plus

2
00:00:04.160 --> 00:00:09.039
<v Speaker 1>plus textbook, right skipping past all the really heavy explanations

3
00:00:09.519 --> 00:00:13.800
<v Speaker 1>and just finding those shimmering nuggets of insight that actually matter.

4
00:00:14.039 --> 00:00:15.759
<v Speaker 2>Yeah, that's pretty much what we're aming for today.

5
00:00:15.800 --> 00:00:16.719
<v Speaker 1>Welcome to the deep dive.

6
00:00:16.920 --> 00:00:20.960
<v Speaker 2>We've taken this comprehensive guide to C plus plus you shared,

7
00:00:21.280 --> 00:00:25.120
<v Speaker 2>which is packed with examples and detailed explanations, and our

8
00:00:25.199 --> 00:00:28.399
<v Speaker 2>mission really is to distill that make it understandable and

9
00:00:28.760 --> 00:00:31.440
<v Speaker 2>you know, immediately applicable for you exactly.

10
00:00:31.879 --> 00:00:34.640
<v Speaker 1>So, whether you're maybe just starting out with programming or

11
00:00:34.640 --> 00:00:39.159
<v Speaker 1>you're looking to really solidify your C plus plus understanding,

12
00:00:39.439 --> 00:00:41.600
<v Speaker 1>we're going to try and pull out the most impactful,

13
00:00:41.719 --> 00:00:44.719
<v Speaker 1>maybe surprising, and just genuinely useful bits.

14
00:00:44.880 --> 00:00:46.759
<v Speaker 2>Yeah, the goal isn't just a summary. We want you

15
00:00:46.759 --> 00:00:49.520
<v Speaker 2>to get the why behind these concepts, how they fit

16
00:00:49.560 --> 00:00:52.920
<v Speaker 2>into the bigger picture of building you know, robust and efficient.

17
00:00:52.560 --> 00:00:55.079
<v Speaker 1>Software, Getting those aha moments.

18
00:00:54.719 --> 00:00:57.840
<v Speaker 2>Absolutely, those moments that turn a definition into real insight.

19
00:00:57.960 --> 00:00:59.880
<v Speaker 1>All right, let's kick things off right at the beginning,

20
00:01:00.159 --> 00:01:03.520
<v Speaker 1>getting your code to actually do something. You've written your program,

21
00:01:03.880 --> 00:01:07.719
<v Speaker 1>probably in a dot cc file. What's the first hurdle?

22
00:01:07.799 --> 00:01:09.519
<v Speaker 1>How do you make the computer understand it well?

23
00:01:09.560 --> 00:01:11.879
<v Speaker 2>The first step is compilation. You'll usually go to your

24
00:01:11.920 --> 00:01:15.519
<v Speaker 2>command line type something like ccprog one dot cc. What

25
00:01:15.640 --> 00:01:18.840
<v Speaker 2>happens then kind of depends on your system. Right on Windows,

26
00:01:18.920 --> 00:01:23.519
<v Speaker 2>you'll typically get an executable file, probably named prog one

27
00:01:23.640 --> 00:01:27.280
<v Speaker 2>dot ex okay, But if you're on a Unix like system,

28
00:01:27.640 --> 00:01:30.760
<v Speaker 2>the compiler often just spits out a generic file called

29
00:01:30.799 --> 00:01:32.040
<v Speaker 2>a dot out.

30
00:01:31.879 --> 00:01:34.519
<v Speaker 1>A dot out, got it, and then the fun part

31
00:01:34.599 --> 00:01:38.560
<v Speaker 1>running it. On Windows, you just type prog one usually.

32
00:01:38.319 --> 00:01:41.640
<v Speaker 2>Yeah, often without the dot ex. But here's a little

33
00:01:41.640 --> 00:01:45.000
<v Speaker 2>snag that often gets beginners. Depending on how your system's

34
00:01:45.000 --> 00:01:46.760
<v Speaker 2>set up, you might need to be explicit about where

35
00:01:46.760 --> 00:01:48.760
<v Speaker 2>the program is, like, tell the shell to look right

36
00:01:48.799 --> 00:01:50.000
<v Speaker 2>here in the current directory.

37
00:01:50.079 --> 00:01:52.480
<v Speaker 1>Ah, so that's the prog one on Windows or a

38
00:01:52.599 --> 00:01:54.760
<v Speaker 1>dot out on Unix exactly.

39
00:01:54.959 --> 00:01:57.519
<v Speaker 2>That little dot slash just means look in this folder.

40
00:01:57.599 --> 00:01:59.159
<v Speaker 2>It's a small thing, but crucial.

41
00:01:59.439 --> 00:02:01.159
<v Speaker 1>And what about after it runs? How do you know

42
00:02:01.200 --> 00:02:03.280
<v Speaker 1>if it worked or you know if something went wrong?

43
00:02:03.439 --> 00:02:06.200
<v Speaker 2>Right? The exit status? That also varies. On Unx, you

44
00:02:06.239 --> 00:02:08.280
<v Speaker 2>type echo dollars to see the status code.

45
00:02:08.360 --> 00:02:08.639
<v Speaker 1>Okay.

46
00:02:08.719 --> 00:02:11.360
<v Speaker 2>On Windows, the command is different. It's echo percent or

47
00:02:11.560 --> 00:02:17.280
<v Speaker 2>level percent understanding this basic handshake, compile, run check the status.

48
00:02:18.479 --> 00:02:21.199
<v Speaker 2>It's well, it's fundamental. You need it to actually build

49
00:02:21.240 --> 00:02:23.039
<v Speaker 2>and debug anything makes sense.

50
00:02:23.120 --> 00:02:24.960
<v Speaker 1>Once you've got that down, you start looking at the

51
00:02:24.960 --> 00:02:27.639
<v Speaker 1>code itself. And it's funny how even simple things like

52
00:02:27.719 --> 00:02:31.280
<v Speaker 1>comments can have these weird little traps. Your source material

53
00:02:31.280 --> 00:02:33.879
<v Speaker 1>actually points this out with some cool exercises. Yeah, like

54
00:02:33.960 --> 00:02:37.400
<v Speaker 1>one on incorrectly nested comments, and then this one std

55
00:02:37.520 --> 00:02:39.080
<v Speaker 1>dot count will cocout.

56
00:02:39.400 --> 00:02:40.719
<v Speaker 2>Why is that one so tricky?

57
00:02:41.080 --> 00:02:44.319
<v Speaker 1>Ah, that's a brilliant example of C plus plus OS precision.

58
00:02:45.039 --> 00:02:48.840
<v Speaker 1>Or you could say it's literal mindedness. Okay, we look

59
00:02:48.879 --> 00:02:50.879
<v Speaker 1>at and we mentally parse it. Right, we see the

60
00:02:50.879 --> 00:02:53.360
<v Speaker 1>command and then the end do But the compiler just

61
00:02:53.680 --> 00:02:57.039
<v Speaker 1>reads characters. It sees DAWs starts a comment, then it

62
00:02:57.080 --> 00:02:59.599
<v Speaker 1>sees inside the quote marks the things. That's the end

63
00:02:59.599 --> 00:03:01.719
<v Speaker 1>of the comment. Then the full laws that follows is

64
00:03:01.800 --> 00:03:06.360
<v Speaker 1>just junk outside of any comment syntax error. Wow. Okay,

65
00:03:06.439 --> 00:03:08.639
<v Speaker 1>so it just sees the first and stops, leaving the

66
00:03:08.639 --> 00:03:10.199
<v Speaker 1>second one hanging exactly.

67
00:03:10.479 --> 00:03:14.639
<v Speaker 2>It shows just how precise, even unforgiving the syntax is

68
00:03:15.319 --> 00:03:16.680
<v Speaker 2>no guessing allowed.

69
00:03:16.840 --> 00:03:20.520
<v Speaker 1>So even comments need care. Okay, beyond that, and basic

70
00:03:20.560 --> 00:03:24.639
<v Speaker 1>output with std dot count. Understanding program flow is vital.

71
00:03:25.080 --> 00:03:27.639
<v Speaker 1>Code doesn't just run top to bottom like a shopping list.

72
00:03:28.000 --> 00:03:31.199
<v Speaker 2>No, that would be incredibly limiting. You need control flow,

73
00:03:31.719 --> 00:03:33.879
<v Speaker 2>and the main tools for that are the wile and

74
00:03:34.039 --> 00:03:37.479
<v Speaker 2>if statements. They let you make decisions and repeat actions.

75
00:03:37.199 --> 00:03:40.520
<v Speaker 1>Right like the example in the source for counting consecutive

76
00:03:40.560 --> 00:03:41.759
<v Speaker 1>inputs precisely.

77
00:03:41.960 --> 00:03:44.000
<v Speaker 2>That's a great example. It uses an if for the

78
00:03:44.120 --> 00:03:47.319
<v Speaker 2>very first number, then a wile loop, probably with another

79
00:03:47.360 --> 00:03:49.520
<v Speaker 2>if inside, to keep reading numbers as long as they're

80
00:03:49.560 --> 00:03:49.840
<v Speaker 2>the same.

81
00:03:49.919 --> 00:03:51.719
<v Speaker 1>So it tracks the current value in its.

82
00:03:51.560 --> 00:03:54.599
<v Speaker 2>Count yeah, and prints the summary when the value finally changes.

83
00:03:54.840 --> 00:03:57.599
<v Speaker 2>It really shows how you combine these simple if and

84
00:03:57.680 --> 00:03:59.719
<v Speaker 2>wileblocks to build practical logic.

85
00:04:00.000 --> 00:04:02.719
<v Speaker 1>And this brings up formatting. The compiler might not care

86
00:04:02.759 --> 00:04:04.080
<v Speaker 1>if your code looks like spaghetti.

87
00:04:04.159 --> 00:04:05.520
<v Speaker 2>Hey nope, not one bit.

88
00:04:05.560 --> 00:04:10.400
<v Speaker 1>But humans sure doo. Readability, consistency, it's crucial, right, especially

89
00:04:10.439 --> 00:04:12.879
<v Speaker 1>for your future self or anyone else trying to understand

90
00:04:12.879 --> 00:04:15.560
<v Speaker 1>it later. Bad formatting can hide bugs.

91
00:04:15.639 --> 00:04:20.720
<v Speaker 2>Oh, absolutely, think of code as communication. Clear communication prevents misunderstandings,

92
00:04:20.759 --> 00:04:25.000
<v Speaker 2>prevents errors. Getting these fundamentals right both function and form

93
00:04:25.199 --> 00:04:25.639
<v Speaker 2>is key.

94
00:04:25.800 --> 00:04:29.600
<v Speaker 1>Okay, moving Beyond those core mechanics, let's talk about organizing

95
00:04:29.680 --> 00:04:33.399
<v Speaker 1>data in a more sophisticated way. C plus plus has

96
00:04:33.399 --> 00:04:36.600
<v Speaker 1>classes for this. What exactly is a class? Why is

97
00:04:36.639 --> 00:04:40.199
<v Speaker 1>it such a big deal compared to just using say

98
00:04:40.279 --> 00:04:40.879
<v Speaker 1>an integer.

99
00:04:41.120 --> 00:04:44.160
<v Speaker 2>A class is basically your way to invent new types

100
00:04:44.199 --> 00:04:46.759
<v Speaker 2>of data in C plus plus A it lets you

101
00:04:46.800 --> 00:04:50.279
<v Speaker 2>bundle together related pieces of information like a books title,

102
00:04:50.399 --> 00:04:53.319
<v Speaker 2>author and price, and the actions you can perform on

103
00:04:53.360 --> 00:04:55.279
<v Speaker 2>that information, like calculating a discount.

104
00:04:55.319 --> 00:04:57.399
<v Speaker 1>So data and operations together exactly.

105
00:04:57.439 --> 00:04:59.519
<v Speaker 2>It's a huge feature because it lets you model real

106
00:04:59.519 --> 00:05:01.759
<v Speaker 2>world thing directly in your code. You're not just juggling

107
00:05:01.839 --> 00:05:04.879
<v Speaker 2>numbers anymore. You're creating these little, self contained objects that

108
00:05:04.920 --> 00:05:09.000
<v Speaker 2>represent concepts from your problem. Makes programs way more intuitive.

109
00:05:09.279 --> 00:05:12.120
<v Speaker 1>That makes sense, So using something like the sales item

110
00:05:12.120 --> 00:05:15.199
<v Speaker 1>class for bookstore sales the sources, you really only need

111
00:05:15.240 --> 00:05:18.759
<v Speaker 1>three things to use it. Its name, where it's definition lives,

112
00:05:18.920 --> 00:05:22.040
<v Speaker 1>usually a header file, and what operations it supports.

113
00:05:22.199 --> 00:05:25.040
<v Speaker 2>Right, you don't necessarily need to know the internal plumbing,

114
00:05:25.120 --> 00:05:27.680
<v Speaker 2>just the public interface how to interact with it.

115
00:05:28.040 --> 00:05:31.160
<v Speaker 1>And these definitions usually go in header files, often ending

116
00:05:31.199 --> 00:05:36.240
<v Speaker 1>in h dot HPP or dot hxx. But standard library

117
00:05:36.240 --> 00:05:38.240
<v Speaker 1>headers like iostream don't have an ending.

118
00:05:38.439 --> 00:05:41.560
<v Speaker 2>Yeah, that's the convention. It helps distinguish your custom types

119
00:05:41.600 --> 00:05:44.879
<v Speaker 2>from the standard ones. It's a big conceptual leap learning to.

120
00:05:44.959 --> 00:05:47.720
<v Speaker 1>Use classes, but we still need the basic building blocks.

121
00:05:47.720 --> 00:05:51.879
<v Speaker 1>The variables. Primitives like characters, integers, floats, and even integers

122
00:05:51.879 --> 00:05:54.959
<v Speaker 1>have quirks, right, like twenty zero, twenty four and zero

123
00:05:55.120 --> 00:05:56.759
<v Speaker 1>x fourteen all being the same value.

124
00:05:56.879 --> 00:05:59.600
<v Speaker 2>Yeah, that's a fun one. They all represent twenty twenty

125
00:05:59.680 --> 00:06:02.720
<v Speaker 2>is desk standard base ten zero two four with the

126
00:06:02.800 --> 00:06:06.040
<v Speaker 2>leading zero tells the compiler it's octal base eight and

127
00:06:06.120 --> 00:06:10.160
<v Speaker 2>zero by fourteen is hexadecimal base sixteen. Usually does it matter,

128
00:06:10.199 --> 00:06:13.040
<v Speaker 2>but sometimes the notation itself implies a different default type,

129
00:06:13.079 --> 00:06:14.079
<v Speaker 2>which can be surprising.

130
00:06:14.360 --> 00:06:19.959
<v Speaker 1>And initialization this seems like a minefield, especially inside functions.

131
00:06:19.959 --> 00:06:22.680
<v Speaker 2>Oh, it can be if you declare, say an end

132
00:06:22.800 --> 00:06:25.079
<v Speaker 2>inside of function and forget to give it a value.

133
00:06:25.439 --> 00:06:29.920
<v Speaker 2>Its value is technically undefined, not zero, Nope, not guaranteed

134
00:06:29.959 --> 00:06:32.160
<v Speaker 2>to be zero. It could be anything that was previously

135
00:06:32.160 --> 00:06:36.079
<v Speaker 2>in that memory location. Using it leads to unpredictable behavior,

136
00:06:36.439 --> 00:06:38.959
<v Speaker 2>really hard to find bugs. It's like assuming an empty

137
00:06:39.000 --> 00:06:40.680
<v Speaker 2>box has what you need inside.

138
00:06:40.759 --> 00:06:43.959
<v Speaker 1>Risky but global variables are zero initialized.

139
00:06:44.120 --> 00:06:48.399
<v Speaker 2>Generally yes, built in types outside functions get zero initialized,

140
00:06:48.680 --> 00:06:52.079
<v Speaker 2>and classes well, they handle their own initialization through constructors.

141
00:06:52.160 --> 00:06:55.680
<v Speaker 1>Okay, Then you have compound types like pointers and the

142
00:06:55.720 --> 00:06:57.360
<v Speaker 1>symbols and doing double duty.

143
00:06:57.480 --> 00:07:00.439
<v Speaker 2>Right. That confuses people In t declares, P is a

144
00:07:00.480 --> 00:07:03.839
<v Speaker 2>pointer to an ind but later phqal five uses the

145
00:07:04.000 --> 00:07:06.399
<v Speaker 2>to de reference the pointer to access the memory location.

146
00:07:06.519 --> 00:07:09.759
<v Speaker 2>P points to same symbol, different job depending on context.

147
00:07:09.879 --> 00:07:11.720
<v Speaker 1>And null pointers are critical.

148
00:07:11.519 --> 00:07:14.759
<v Speaker 2>Absolutely critical. You can get one using olptr that's the

149
00:07:14.920 --> 00:07:18.680
<v Speaker 2>modern C plus plus way, or sometimes just zero or

150
00:07:18.720 --> 00:07:22.160
<v Speaker 2>the older null macro. The key is always check if

151
00:07:22.199 --> 00:07:24.279
<v Speaker 2>a pointer is null before you try to use on it.

152
00:07:24.680 --> 00:07:27.480
<v Speaker 2>Dear referencing a null pointer is usually an instant crash.

153
00:07:27.560 --> 00:07:31.959
<v Speaker 1>To make things safer, we have cost and constexper const

154
00:07:32.000 --> 00:07:35.120
<v Speaker 1>means a value can't be changed after initialization, right.

155
00:07:35.319 --> 00:07:38.199
<v Speaker 2>And consextper goes further. It means the value must be

156
00:07:38.240 --> 00:07:40.639
<v Speaker 2>known at compile time. The compiler has to be able

157
00:07:40.680 --> 00:07:42.600
<v Speaker 2>to figure it out before the program even runs.

158
00:07:42.879 --> 00:07:46.160
<v Speaker 1>Interesting that some things like sales item or standard iostreams

159
00:07:46.480 --> 00:07:48.920
<v Speaker 1>can't be const exper They're not literal types.

160
00:07:49.040 --> 00:07:52.120
<v Speaker 2>Yeah, they rely on runtime state or operations that just

161
00:07:52.160 --> 00:07:56.240
<v Speaker 2>aren't fixed at compile time. Also, context per pointers have restrictions.

162
00:07:56.279 --> 00:07:59.199
<v Speaker 2>They generally have to point to objects with fixed memory addresses,

163
00:07:59.279 --> 00:08:00.720
<v Speaker 2>not local very on the stack.

164
00:08:00.879 --> 00:08:05.560
<v Speaker 1>So understanding these type details initialization pointers const is fundamental

165
00:08:05.560 --> 00:08:07.560
<v Speaker 1>to avoiding those nasty subtle bugs.

166
00:08:07.639 --> 00:08:10.879
<v Speaker 2>It really is const and cons textper help the compiler

167
00:08:11.000 --> 00:08:13.879
<v Speaker 2>enforce guarantees for you making code safer, but you need

168
00:08:13.920 --> 00:08:14.720
<v Speaker 2>to know their rules.

169
00:08:14.959 --> 00:08:17.920
<v Speaker 1>Okay. When unique collections of data, the standard library gives

170
00:08:17.959 --> 00:08:21.240
<v Speaker 1>you great tools. String is the obvious one for text,

171
00:08:21.480 --> 00:08:23.839
<v Speaker 1>and like the int example earlier, you can read lots

172
00:08:23.879 --> 00:08:26.279
<v Speaker 1>of strings without knowing how many beforehand.

173
00:08:25.920 --> 00:08:28.560
<v Speaker 2>Very flexible. And then there's vector, which is like a

174
00:08:28.639 --> 00:08:32.320
<v Speaker 2>dynamic array. It can grow or shrink as needed. Modern

175
00:08:32.399 --> 00:08:35.159
<v Speaker 2>C plus plus lets you initialize them nicely with curly

176
00:08:35.200 --> 00:08:37.840
<v Speaker 2>braces like vectorant v one two three clean.

177
00:08:38.080 --> 00:08:41.080
<v Speaker 1>But vectors have a dark side, right yeah, subscripting.

178
00:08:40.679 --> 00:08:44.360
<v Speaker 2>Ah, yes, the danger zone. The source gives this example

179
00:08:44.519 --> 00:08:47.720
<v Speaker 2>vectorant of a C two ten cut evac two ten.

180
00:08:47.960 --> 00:08:48.759
<v Speaker 2>What's wrong there?

181
00:08:48.879 --> 00:08:51.639
<v Speaker 1>Well, ivac two has ten elements, so the valid indicase

182
00:08:51.679 --> 00:08:54.639
<v Speaker 1>are zero through nine. Ivax two ten is one.

183
00:08:54.519 --> 00:08:56.679
<v Speaker 2>Past the end exactly, it's out of bounds. And the

184
00:08:56.720 --> 00:08:59.279
<v Speaker 2>really scary part the compiler probably won't warn you.

185
00:08:59.559 --> 00:09:01.200
<v Speaker 1>It just compiles often.

186
00:09:01.039 --> 00:09:03.440
<v Speaker 2>Yes, and at runtime you get undefined behavior.

187
00:09:03.559 --> 00:09:05.679
<v Speaker 1>And undefined behavior isn't just a crash, is it. It

188
00:09:05.679 --> 00:09:06.840
<v Speaker 1>could be worse, much worse.

189
00:09:06.919 --> 00:09:09.440
<v Speaker 2>It means anything could happen. It might crash. It might

190
00:09:09.480 --> 00:09:11.559
<v Speaker 2>seem to work fine on your machine but crash later.

191
00:09:11.639 --> 00:09:14.960
<v Speaker 2>For a user, it might silently corrupt other data or

192
00:09:15.360 --> 00:09:16.960
<v Speaker 2>and this is the big one, it could create a

193
00:09:17.000 --> 00:09:20.759
<v Speaker 2>security hole because you might be reading or writing memory

194
00:09:20.799 --> 00:09:23.399
<v Speaker 2>that doesn't belong to the vector. This is the classic

195
00:09:23.480 --> 00:09:27.000
<v Speaker 2>buffer overflow. The source rightly calls it the most common

196
00:09:27.039 --> 00:09:31.360
<v Speaker 2>cause of security problems. Accessing IVEC two ten could potentially

197
00:09:31.399 --> 00:09:35.639
<v Speaker 2>overwrite crucial program data or even allow malicious code execution.

198
00:09:35.879 --> 00:09:36.879
<v Speaker 2>It's a huge deal.

199
00:09:37.200 --> 00:09:40.000
<v Speaker 1>Wow. Okay, that really hammers home why bounds checking is

200
00:09:40.039 --> 00:09:43.279
<v Speaker 1>so important. So compared to flexible vectors, we also have

201
00:09:43.360 --> 00:09:45.559
<v Speaker 1>plane old arrays fixed size.

202
00:09:45.320 --> 00:09:48.360
<v Speaker 2>YEP built in a arrays fixed size determined at compile time.

203
00:09:48.799 --> 00:09:51.120
<v Speaker 2>You typically use size it for indices, which is an

204
00:09:51.200 --> 00:09:54.639
<v Speaker 2>unsigned type suitable for sizes. You can have multidimensional ones.

205
00:09:54.440 --> 00:09:57.080
<v Speaker 1>Too, But the source in exercise three point twenty nine

206
00:09:57.399 --> 00:09:58.720
<v Speaker 1>kind of hints they have drawbacks.

207
00:09:58.720 --> 00:10:01.480
<v Speaker 2>They do raw rays lie lack the flexibility and safety

208
00:10:01.519 --> 00:10:03.919
<v Speaker 2>features of vector. They don't know their own size, they

209
00:10:03.919 --> 00:10:07.039
<v Speaker 2>decay into pointers easily, and managing their memory manually is

210
00:10:07.159 --> 00:10:09.960
<v Speaker 2>error prone. That's why vector is almost always referred to

211
00:10:10.039 --> 00:10:13.480
<v Speaker 2>Modern C plus plus ibros. Arrays have their place, but

212
00:10:13.519 --> 00:10:15.879
<v Speaker 2>you need to be aware of the pitfalls.

213
00:10:15.480 --> 00:10:19.440
<v Speaker 1>To navigate these containers vectors, strings, etc. We have iterators.

214
00:10:19.799 --> 00:10:22.200
<v Speaker 1>You describe them as like a smart pointer or GPS

215
00:10:22.200 --> 00:10:22.799
<v Speaker 1>for data.

216
00:10:22.919 --> 00:10:25.759
<v Speaker 2>Yeah, that's a good analogy. An iterator points to an

217
00:10:25.799 --> 00:10:28.960
<v Speaker 2>element within a container. You use the star operator to

218
00:10:28.960 --> 00:10:32.279
<v Speaker 2>get the element's value be referencing, and the plus plus

219
00:10:32.320 --> 00:10:34.480
<v Speaker 2>plus plus operator to move to the next element.

220
00:10:34.639 --> 00:10:36.919
<v Speaker 1>And the cool thing is they work across different containers.

221
00:10:37.039 --> 00:10:41.360
<v Speaker 2>That's the power. They provide a uniform interface. The code

222
00:10:41.399 --> 00:10:44.960
<v Speaker 2>to loop through a vector using iterators looks very similar

223
00:10:45.000 --> 00:10:48.200
<v Speaker 2>to code lipping through a list or a deck. Some iterators,

224
00:10:48.240 --> 00:10:51.559
<v Speaker 2>like those for straying, vector deck and array, even support arithmetic.

225
00:10:51.799 --> 00:10:54.360
<v Speaker 2>You can jump forward five elements, for instance.

226
00:10:54.000 --> 00:10:56.799
<v Speaker 1>And there are different kinds like read only ones.

227
00:10:56.919 --> 00:11:00.000
<v Speaker 2>Yep, you have iterator for read write access. Can still

228
00:11:00.000 --> 00:11:02.360
<v Speaker 2>iterator for rate only safer if you don't need to

229
00:11:02.360 --> 00:11:06.440
<v Speaker 2>modify and even reverse iterator to go backwards using prey

230
00:11:06.440 --> 00:11:10.440
<v Speaker 2>again and send always gives you considerators. This generalization makes

231
00:11:10.480 --> 00:11:12.320
<v Speaker 2>algorithms incredibly reusable.

232
00:11:12.440 --> 00:11:14.879
<v Speaker 1>It makes sense. And strings aren't just for basic io.

233
00:11:15.000 --> 00:11:16.679
<v Speaker 1>They have advanced operations too.

234
00:11:16.759 --> 00:11:20.759
<v Speaker 2>Oh yeah, things like append a sign, insert, replace give

235
00:11:20.840 --> 00:11:24.639
<v Speaker 2>you fine grain control over modifying string content and searching.

236
00:11:24.799 --> 00:11:27.519
<v Speaker 2>The fine function is key. You give it a substring

237
00:11:27.759 --> 00:11:30.240
<v Speaker 2>and it returns the starting position, which is a string

238
00:11:30.440 --> 00:11:33.919
<v Speaker 2>dot size type, an unsigned value, or a special value

239
00:11:33.960 --> 00:11:37.519
<v Speaker 2>called in pauses. If the substring isn't found, remember it's

240
00:11:37.600 --> 00:11:41.080
<v Speaker 2>case sensitive. Find won't find find these tools let you

241
00:11:41.120 --> 00:11:43.039
<v Speaker 2>do some pretty sophisticated text processing.

242
00:11:43.120 --> 00:11:46.200
<v Speaker 1>Okay, we've covered basics data structures. Let's get into the

243
00:11:46.200 --> 00:11:49.519
<v Speaker 1>more advanced stuff. Operators they're everywhere c plus plus foe

244
00:11:49.600 --> 00:11:52.320
<v Speaker 1>and not just for math into your division. For example,

245
00:11:52.679 --> 00:11:53.919
<v Speaker 1>ten three is three.

246
00:11:53.919 --> 00:11:57.240
<v Speaker 2>Right truncation, It just chops off the fractional part. No

247
00:11:57.399 --> 00:11:59.559
<v Speaker 2>rounding can definitely catch you off guard if you expect

248
00:11:59.639 --> 00:12:00.759
<v Speaker 2>floating point behavior.

249
00:12:00.919 --> 00:12:04.320
<v Speaker 1>And what about signed integer wrap around the source manages three, two, seven, six,

250
00:12:04.440 --> 00:12:06.279
<v Speaker 1>eight becoming positive if you subtract one.

251
00:12:06.519 --> 00:12:09.679
<v Speaker 2>Ah yeah, that's about integer overflow with signed types. If

252
00:12:09.759 --> 00:12:13.240
<v Speaker 2>you go below the minimum value like NACS three two, seven,

253
00:12:13.320 --> 00:12:16.120
<v Speaker 2>six eight for a sixteen bit short. The behavior is

254
00:12:16.159 --> 00:12:19.679
<v Speaker 2>technically undefined in standards C plus plus set. It might

255
00:12:19.679 --> 00:12:22.440
<v Speaker 2>wrap around to the maximum positive value on some systems,

256
00:12:22.519 --> 00:12:25.240
<v Speaker 2>or it might crash or do something else weird. It

257
00:12:25.320 --> 00:12:28.039
<v Speaker 2>highlights that C plus plus operates close to the hardware,

258
00:12:28.120 --> 00:12:29.679
<v Speaker 2>and you need to be careful about the limits of

259
00:12:29.720 --> 00:12:33.159
<v Speaker 2>your types. Unsigned integers, however, are defined to wrap around

260
00:12:33.240 --> 00:12:33.879
<v Speaker 2>good distinction.

261
00:12:34.000 --> 00:12:36.679
<v Speaker 1>Another operator is the conditional operator.

262
00:12:36.320 --> 00:12:39.759
<v Speaker 2>De ternary operator yeah, superconcise for simple of false assignments

263
00:12:39.919 --> 00:12:43.759
<v Speaker 2>result condition and value value of false. Very handy and

264
00:12:43.879 --> 00:12:47.840
<v Speaker 2>bitwise operators yeah yeah for manipulating individual bits left shift,

265
00:12:47.919 --> 00:12:48.759
<v Speaker 2>right shift, viz.

266
00:12:49.000 --> 00:12:49.639
<v Speaker 1>Not aid.

267
00:12:51.279 --> 00:12:54.120
<v Speaker 2>One key detail is that right shifting as signed negative

268
00:12:54.159 --> 00:12:57.080
<v Speaker 2>number is implementation defined. It might fill the new bits

269
00:12:57.120 --> 00:13:00.919
<v Speaker 2>with one's arithmetic shift or zero's logical shift. Write shifting

270
00:13:00.919 --> 00:13:04.080
<v Speaker 2>an unsigned number always fills with zeros, important if you're

271
00:13:04.080 --> 00:13:05.919
<v Speaker 2>doing low level bit tooidly CEE.

272
00:13:05.759 --> 00:13:08.559
<v Speaker 1>Plus plus also has explicit type conversions, the.

273
00:13:08.639 --> 00:13:11.799
<v Speaker 2>Casts right stata cast is the most common used for

274
00:13:11.879 --> 00:13:15.039
<v Speaker 2>sensible conversions like int to double or up down an

275
00:13:15.039 --> 00:13:18.799
<v Speaker 2>inheritance hierarchy when you know it's safe. Const cast is

276
00:13:18.840 --> 00:13:22.080
<v Speaker 2>specifically for removing cost, usually a sign you should rethink

277
00:13:22.120 --> 00:13:24.879
<v Speaker 2>your design, but sometimes necessary.

278
00:13:24.360 --> 00:13:27.120
<v Speaker 1>And the dangerous one reinterpret cast.

279
00:13:27.279 --> 00:13:30.039
<v Speaker 2>Yeah, that's the break glass in case of emergency cast.

280
00:13:30.399 --> 00:13:33.799
<v Speaker 2>It tells the compiler to just reinterpret the raw bits

281
00:13:33.799 --> 00:13:35.960
<v Speaker 2>of one type as if they were another type, even

282
00:13:36.000 --> 00:13:39.600
<v Speaker 2>if they're completely unrelated. Like your analogy telling it. English

283
00:13:39.600 --> 00:13:43.240
<v Speaker 2>text is actually ancient Greek. It's powerful for low level stuff,

284
00:13:43.279 --> 00:13:46.799
<v Speaker 2>but incredibly easy to misuse and cause crashes or weird behavior.

285
00:13:47.279 --> 00:13:49.279
<v Speaker 2>Avoid unless you absolutely have to.

286
00:13:49.559 --> 00:13:53.120
<v Speaker 1>What's really cool is operator overloading. Defining what plus or

287
00:13:53.240 --> 00:13:55.399
<v Speaker 1>means for your own classes like sale.

288
00:13:55.159 --> 00:13:58.360
<v Speaker 2>Side exactly, you can make your custom types behave intuitively,

289
00:13:58.600 --> 00:14:00.919
<v Speaker 2>item one plus item two could some sales item one,

290
00:14:01.000 --> 00:14:04.000
<v Speaker 2>egles item too could compare isbn's makes code.

291
00:14:03.840 --> 00:14:06.039
<v Speaker 1>Very readable, but you can't mess with built in types

292
00:14:06.240 --> 00:14:07.759
<v Speaker 1>like redefining NT plus NT.

293
00:14:08.000 --> 00:14:10.720
<v Speaker 2>Thankfully no, that would be chaos. You can only overload

294
00:14:10.759 --> 00:14:13.519
<v Speaker 2>operators where at least one operand is a user defined type,

295
00:14:13.759 --> 00:14:14.840
<v Speaker 2>a class or enom.

296
00:14:15.120 --> 00:14:17.440
<v Speaker 1>What operators are commonly overloaded.

297
00:14:17.159 --> 00:14:22.279
<v Speaker 2>Well, arithmetic operators plus aisle, comparison operators, assignment, subscript function

298
00:14:22.399 --> 00:14:26.840
<v Speaker 2>call stream insertion extraction. Defining is often useful for custom

299
00:14:26.919 --> 00:14:29.399
<v Speaker 2>classes so they can be easily sorted or used in

300
00:14:29.559 --> 00:14:31.840
<v Speaker 2>ordered containers like std dot map.

301
00:14:31.840 --> 00:14:35.279
<v Speaker 1>And the function call operate operator that makes an object

302
00:14:35.279 --> 00:14:36.559
<v Speaker 1>act like a function. Yeah.

303
00:14:36.679 --> 00:14:39.639
<v Speaker 2>It lets you create function objects or functors. You can

304
00:14:39.679 --> 00:14:43.000
<v Speaker 2>instance an object and then call it with parentheses like

305
00:14:43.279 --> 00:14:47.360
<v Speaker 2>myfunctor R one R two. It's a precursor to lambdas

306
00:14:47.440 --> 00:14:50.519
<v Speaker 2>and heavily used in the standard library, especially with algorithms.

307
00:14:50.600 --> 00:14:54.000
<v Speaker 1>So operators are fundamental and customizing them as powerful. Let's

308
00:14:54.000 --> 00:14:57.399
<v Speaker 1>talk functions the workhorses, like the example for factors.

309
00:14:57.440 --> 00:15:00.960
<v Speaker 2>Simple function call takes an argument, returns about the basic

310
00:15:01.120 --> 00:15:02.320
<v Speaker 2>unit of code organization.

311
00:15:02.480 --> 00:15:04.399
<v Speaker 1>And for bigger projects you split code up.

312
00:15:04.480 --> 00:15:09.279
<v Speaker 2>Separate compilation absolutely essential. You put declarations in header files

313
00:15:09.360 --> 00:15:13.919
<v Speaker 2>JOJHPP and definitions in source files dot CC, dot CPP.

314
00:15:14.159 --> 00:15:16.759
<v Speaker 2>You compile source files individually and then link them together.

315
00:15:17.159 --> 00:15:19.120
<v Speaker 2>If you only change one file, you only need to

316
00:15:19.159 --> 00:15:22.600
<v Speaker 2>recompile that one file, not the whole project. Saves tons

317
00:15:22.600 --> 00:15:22.960
<v Speaker 2>of time.

318
00:15:23.120 --> 00:15:27.000
<v Speaker 1>And how you pass arguments matters pass by value versus

319
00:15:27.120 --> 00:15:29.360
<v Speaker 1>pass by reference huge difference.

320
00:15:29.440 --> 00:15:31.799
<v Speaker 2>Pass by value makes a copy of the argument. The

321
00:15:31.840 --> 00:15:34.720
<v Speaker 2>function works on the copy. The original outside the function

322
00:15:34.840 --> 00:15:39.360
<v Speaker 2>is untouched. Pass by reference using in the parameter type

323
00:15:39.399 --> 00:15:43.600
<v Speaker 2>like void reset into passes the actual variable. The function

324
00:15:43.720 --> 00:15:46.799
<v Speaker 2>can directly modify the original variable and the caller scope.

325
00:15:47.240 --> 00:15:49.279
<v Speaker 2>Use reference when you want the function to change the

326
00:15:49.399 --> 00:15:52.320
<v Speaker 2>argument or for large objects to avoid the cost of copying.

327
00:15:52.480 --> 00:15:54.960
<v Speaker 1>In functions return arrays not directly.

328
00:15:55.080 --> 00:15:57.519
<v Speaker 2>You can't declare a function to return an array type,

329
00:15:57.799 --> 00:15:59.960
<v Speaker 2>but you can return a pointer to the first l

330
00:16:00.000 --> 00:16:02.759
<v Speaker 2>element of an array or reference to an array, or

331
00:16:02.960 --> 00:16:06.480
<v Speaker 2>better yet, return a std dot vector or std dot array.

332
00:16:06.639 --> 00:16:11.840
<v Speaker 1>C plus plus also has overloaded functions same name, different parameters.

333
00:16:11.559 --> 00:16:15.120
<v Speaker 2>Right, like having print double and print constring. The compiler

334
00:16:15.120 --> 00:16:17.159
<v Speaker 2>figures out which want to call based on the arguments

335
00:16:17.159 --> 00:16:22.919
<v Speaker 2>you provide. Even constants can differentiate overloads. Void foo sorts

336
00:16:22.960 --> 00:16:26.600
<v Speaker 2>wiget in and void food conswigit in are different functions.

337
00:16:26.279 --> 00:16:29.440
<v Speaker 1>And inside member functions there's this pointer. Yep.

338
00:16:29.919 --> 00:16:33.399
<v Speaker 2>This is an implicit pointer available inside every non static

339
00:16:33.519 --> 00:16:36.919
<v Speaker 2>member function. It points to the specific object the member

340
00:16:36.919 --> 00:16:39.720
<v Speaker 2>function was called on. Is how the function knows which

341
00:16:39.720 --> 00:16:43.519
<v Speaker 2>objects data to access, and this itself is a constant pointer.

342
00:16:43.639 --> 00:16:46.120
<v Speaker 2>You can change the data points to, but you can't

343
00:16:46.120 --> 00:16:47.840
<v Speaker 2>make this point to a different object.

344
00:16:48.000 --> 00:16:49.799
<v Speaker 1>What about constant member functions?

345
00:16:50.080 --> 00:16:53.440
<v Speaker 2>AH very important If you declare a member function with

346
00:16:53.480 --> 00:16:56.559
<v Speaker 2>const after the parameter list like double salees, item, dot, ivery,

347
00:16:56.600 --> 00:16:59.759
<v Speaker 2>g price, const, you're promising that this function will not

348
00:16:59.759 --> 00:17:02.440
<v Speaker 2>show change any data members of the object. It's read only.

349
00:17:03.039 --> 00:17:05.720
<v Speaker 2>This lets you call the function on const objects and

350
00:17:05.759 --> 00:17:07.279
<v Speaker 2>improves safety and clarity.

351
00:17:07.480 --> 00:17:10.519
<v Speaker 1>Then there are constructors for initializing objects. Yeah, the source

352
00:17:10.599 --> 00:17:12.400
<v Speaker 1>really emphasizes initializer lists.

353
00:17:12.799 --> 00:17:17.680
<v Speaker 2>Yes. Constructor initializer lists number one, vowel one, member two,

354
00:17:17.839 --> 00:17:21.640
<v Speaker 2>valve two are the preferred way to initialize members. They

355
00:17:21.680 --> 00:17:25.720
<v Speaker 2>initialize members before the constructor body starts executing. This is

356
00:17:25.799 --> 00:17:29.160
<v Speaker 2>crucial for cost members, reference members, and often more efficient

357
00:17:29.200 --> 00:17:30.240
<v Speaker 2>for class type members.

358
00:17:30.559 --> 00:17:33.680
<v Speaker 1>And the order matters, but not the order in the

359
00:17:33.720 --> 00:17:34.359
<v Speaker 1>list correct.

360
00:17:34.440 --> 00:17:36.799
<v Speaker 2>That's a common trap. Members are initialized in the order

361
00:17:36.799 --> 00:17:39.440
<v Speaker 2>they are declared in the class definition, regardless of the

362
00:17:39.519 --> 00:17:42.240
<v Speaker 2>order in the initializer list. Get the list order wrong

363
00:17:42.359 --> 00:17:45.240
<v Speaker 2>relative to the declaration order, and you can get subtle

364
00:17:45.240 --> 00:17:48.240
<v Speaker 2>bugs if one member's initialization depends on another.

365
00:17:48.680 --> 00:17:51.079
<v Speaker 1>You can also have default arguments and constructors.

366
00:17:51.319 --> 00:17:55.960
<v Speaker 2>Yeah, like sales, data, std dot string s equals this.

367
00:17:56.000 --> 00:17:58.960
<v Speaker 2>One constructor can now act as the default constructor if

368
00:17:59.000 --> 00:18:02.160
<v Speaker 2>called with no arguments or take a string argument. Very

369
00:18:02.160 --> 00:18:05.440
<v Speaker 2>flexible and you can have delegating constructors where one constructor

370
00:18:05.480 --> 00:18:08.119
<v Speaker 2>calls another in the same class using the initializer list

371
00:18:08.119 --> 00:18:11.039
<v Speaker 2>syntax to avoid repeating common setup code.

372
00:18:11.200 --> 00:18:13.079
<v Speaker 1>What about friend functions or classes.

373
00:18:13.519 --> 00:18:17.680
<v Speaker 2>Friend declarations grant special access. A function or another class

374
00:18:17.720 --> 00:18:20.720
<v Speaker 2>declared as a friend inside class A can access a's

375
00:18:20.799 --> 00:18:25.519
<v Speaker 2>private and protected members. It breaks encapsulation, so use it sparingly.

376
00:18:25.920 --> 00:18:29.119
<v Speaker 2>But sometimes it's the cleanest solution, especially for things like

377
00:18:29.279 --> 00:18:33.480
<v Speaker 2>operator overloading. Like operator and even if you define a

378
00:18:33.519 --> 00:18:37.200
<v Speaker 2>friend function entirely inside the class body, you usually still

379
00:18:37.240 --> 00:18:39.839
<v Speaker 2>need a separate declaration outside the class to make it

380
00:18:39.960 --> 00:18:41.960
<v Speaker 2>visible in the surrounding scope.

381
00:18:41.599 --> 00:18:45.319
<v Speaker 1>And name resolution. Names inside a class can hide names

382
00:18:45.359 --> 00:18:45.960
<v Speaker 1>from outside.

383
00:18:46.039 --> 00:18:49.079
<v Speaker 2>Yes, s popes matter. If a member function uses a name,

384
00:18:49.319 --> 00:18:52.519
<v Speaker 2>the compiler looks first within the function, then within the class,

385
00:18:52.599 --> 00:18:55.480
<v Speaker 2>then in outer scopes. A member name can hide a

386
00:18:55.559 --> 00:18:59.319
<v Speaker 2>global variable or function with the same name. Understanding scope

387
00:18:59.319 --> 00:19:02.240
<v Speaker 2>resolution rules is key to avoiding confusion.

388
00:19:02.559 --> 00:19:07.200
<v Speaker 1>Mastering all these function aspects. Overloading const constructor's scope is

389
00:19:07.279 --> 00:19:09.720
<v Speaker 1>really crucial for well structured C plus plus code.

390
00:19:09.799 --> 00:19:12.559
<v Speaker 2>Absolutely, they're the building blocks of your program's architecture.

391
00:19:12.599 --> 00:19:15.440
<v Speaker 1>Okay, let's tackle a big topic, memory management. We have

392
00:19:15.480 --> 00:19:18.920
<v Speaker 1>the stack for local variables automatically managed. But then there's

393
00:19:18.920 --> 00:19:20.279
<v Speaker 1>the heap or free.

394
00:19:20.039 --> 00:19:24.680
<v Speaker 2>Store right where you dynamically allocate memory using new objects

395
00:19:24.680 --> 00:19:28.759
<v Speaker 2>created with new live until you explicitly destroy them using delete.

396
00:19:28.599 --> 00:19:31.680
<v Speaker 1>And forgetting to delete leads to memory leaks. Doing it

397
00:19:31.720 --> 00:19:33.839
<v Speaker 1>wrong leads to crashes exactly.

398
00:19:34.359 --> 00:19:37.880
<v Speaker 2>Manual memory management is notoriously error prone in C plus

399
00:19:37.880 --> 00:19:39.400
<v Speaker 2>plus REE, which.

400
00:19:39.200 --> 00:19:43.200
<v Speaker 1>Brings us to smart pointers. The modern C plus plus solution.

401
00:19:43.119 --> 00:19:46.640
<v Speaker 2>Yes, share ptr is a big one. It uses reference counting.

402
00:19:47.119 --> 00:19:50.079
<v Speaker 2>Multiple shared PTRs can point to the same object. The

403
00:19:50.119 --> 00:19:53.400
<v Speaker 2>object is automatically deleted only when the last share ptr

404
00:19:53.480 --> 00:19:54.559
<v Speaker 2>pointing to it goes away.

405
00:19:54.640 --> 00:19:57.799
<v Speaker 1>Sounds great, but the source highlights a critical error involving

406
00:19:57.880 --> 00:19:58.880
<v Speaker 1>get ah.

407
00:19:58.960 --> 00:20:01.920
<v Speaker 2>Yes, the double delete. It's subtle but deadly. Let's walk

408
00:20:01.920 --> 00:20:05.880
<v Speaker 2>through it. You create shared print P new D forty two. Okay,

409
00:20:05.880 --> 00:20:07.839
<v Speaker 2>P owns the interter reference count as one.

410
00:20:07.920 --> 00:20:08.119
<v Speaker 1>Right.

411
00:20:08.200 --> 00:20:10.680
<v Speaker 2>Then you do int qx and p bet get gives

412
00:20:10.680 --> 00:20:13.920
<v Speaker 2>you the raw pointer, but importantly, it doesn't affect PA's

413
00:20:14.000 --> 00:20:16.519
<v Speaker 2>reference count. P still thinks it's the sole owner.

414
00:20:16.759 --> 00:20:18.640
<v Speaker 1>Okay, Q is just a raw pointer looking at the

415
00:20:18.640 --> 00:20:19.039
<v Speaker 1>same D.

416
00:20:19.640 --> 00:20:24.160
<v Speaker 2>Now the killer line. You create a new temporary shared

417
00:20:24.200 --> 00:20:26.680
<v Speaker 2>piece you are directly from the raw pointer Q. This

418
00:20:26.759 --> 00:20:29.720
<v Speaker 2>ten pointer also thinks it owns the memory it doesn't

419
00:20:29.720 --> 00:20:32.559
<v Speaker 2>know about p oh dear. When Temp goes out of

420
00:20:32.599 --> 00:20:35.920
<v Speaker 2>scope at the closing brace, its reference count drops to zero,

421
00:20:36.359 --> 00:20:38.359
<v Speaker 2>so it deletes the memory pointed to by Q.

422
00:20:38.759 --> 00:20:42.240
<v Speaker 1>So the memory is gone, but PEA still exists exactly.

423
00:20:42.559 --> 00:20:45.039
<v Speaker 2>P is now a dangling pointer. It's pointing to memory

424
00:20:45.079 --> 00:20:48.079
<v Speaker 2>that's been freed. Later, when P itself goes out of scope,

425
00:20:48.079 --> 00:20:51.160
<v Speaker 2>it tries to delete the same memory again. Boom, double deletion,

426
00:20:51.440 --> 00:20:53.279
<v Speaker 2>undefined behavior likely crash.

427
00:20:53.359 --> 00:20:56.440
<v Speaker 1>Wow. So the rule is never create a new owning

428
00:20:56.480 --> 00:20:59.319
<v Speaker 1>smart pointer from a raw pointer obtained via get from

429
00:20:59.359 --> 00:21:00.000
<v Speaker 1>another smart part.

430
00:21:00.279 --> 00:21:03.359
<v Speaker 2>Precisely, that's a huge aha moment. I get is for

431
00:21:03.519 --> 00:21:07.359
<v Speaker 2>observation or passing to legacy, c APIs not for creating

432
00:21:07.400 --> 00:21:08.160
<v Speaker 2>more owners What.

433
00:21:08.039 --> 00:21:09.559
<v Speaker 1>About other smart pointers unique a.

434
00:21:09.599 --> 00:21:13.799
<v Speaker 2>Points unicopter enforces exclusive ownership. Only one unicopter can own

435
00:21:13.799 --> 00:21:17.079
<v Speaker 2>a resource at any time. You can transfer ownership using

436
00:21:17.160 --> 00:21:19.559
<v Speaker 2>std dot move, but you can't copy it. It's very

437
00:21:19.599 --> 00:21:22.279
<v Speaker 2>lightweight and the preferred choice when you don't need shared ownership.

438
00:21:22.319 --> 00:21:24.480
<v Speaker 2>It replaced the old unsafe.

439
00:21:24.039 --> 00:21:25.839
<v Speaker 1>Autopturra and weak ptr.

440
00:21:26.200 --> 00:21:29.440
<v Speaker 2>Week ptr is used in conjunction with shared ptr to

441
00:21:29.480 --> 00:21:33.000
<v Speaker 2>break ownership cycles. If object A has a shared ptr

442
00:21:33.039 --> 00:21:35.640
<v Speaker 2>to B and B has a shared ptr back to A,

443
00:21:36.279 --> 00:21:39.559
<v Speaker 2>neither will ever be deleted. A week ptr holds a

444
00:21:39.599 --> 00:21:42.519
<v Speaker 2>non owning reference. It lets you access the object if

445
00:21:42.519 --> 00:21:44.200
<v Speaker 2>it still exists, but doesn't keep it alive.

446
00:21:44.400 --> 00:21:47.000
<v Speaker 1>So smart pointers automated memory management, but you still need

447
00:21:47.039 --> 00:21:48.319
<v Speaker 1>to understand their rules.

448
00:21:48.359 --> 00:21:52.799
<v Speaker 2>Absolutely. They solve many problems, but introduce their own nuances.

449
00:21:53.240 --> 00:21:56.480
<v Speaker 2>Understand them, use them correctly, and your C plus plus

450
00:21:56.519 --> 00:21:58.839
<v Speaker 2>code becomes much safer and easier to manage.

451
00:21:58.920 --> 00:22:04.240
<v Speaker 1>Okay, let's shift gears to object oriented programming OOP. Inheritance

452
00:22:04.279 --> 00:22:09.359
<v Speaker 1>The inheritance the is a relationship. The source uses quote

453
00:22:09.440 --> 00:22:10.400
<v Speaker 1>end bulk quote.

454
00:22:10.279 --> 00:22:14.039
<v Speaker 2>Right class bulkwart public quote means bulk quote. Inherits from quote.

455
00:22:14.079 --> 00:22:16.839
<v Speaker 2>It gets quotes, members and capabilities, and can add its

456
00:22:16.880 --> 00:22:20.119
<v Speaker 2>own or override base class behavior. The override keyword is

457
00:22:20.160 --> 00:22:22.519
<v Speaker 2>good practice. You put it on derived class functions that

458
00:22:22.559 --> 00:22:24.680
<v Speaker 2>are meant to override a virtual function in the base.

459
00:22:25.160 --> 00:22:29.160
<v Speaker 2>The compiler checks that you actually are overwriting something, preventing typos.

460
00:22:28.839 --> 00:22:31.759
<v Speaker 1>And this ties into dynamic binding and virtual functions.

461
00:22:32.039 --> 00:22:36.440
<v Speaker 2>Yes, this is where OP gets really powerful. If you

462
00:22:36.559 --> 00:22:40.519
<v Speaker 2>have a base class pointer like quote that actually points

463
00:22:40.559 --> 00:22:43.680
<v Speaker 2>to a derived object like a bulk quote, and you

464
00:22:43.759 --> 00:22:47.039
<v Speaker 2>call a virtual function through that pointer, like net price.

465
00:22:47.799 --> 00:22:51.599
<v Speaker 2>Dynamic binding ensures the derived classes version bulk quote dot

466
00:22:51.599 --> 00:22:53.559
<v Speaker 2>net price gets called at runtime, so.

467
00:22:53.559 --> 00:22:56.400
<v Speaker 1>The program figures out the object's actual type at run

468
00:22:56.480 --> 00:22:57.279
<v Speaker 1>time exactly.

469
00:22:57.359 --> 00:23:00.519
<v Speaker 2>It distinguishes between the static type what the point of

470
00:23:00.559 --> 00:23:03.680
<v Speaker 2>reference is declared as or exactly, and the dynamic type

471
00:23:03.920 --> 00:23:06.559
<v Speaker 2>what the object really is at runtime. Example, bulk quote

472
00:23:06.680 --> 00:23:09.480
<v Speaker 2>virtual functions are dispatched based on the dynamic type. Non

473
00:23:09.559 --> 00:23:11.960
<v Speaker 2>virtual functions are dispatched based on the static type.

474
00:23:12.000 --> 00:23:13.720
<v Speaker 1>And you can't go the other way, right. A base

475
00:23:13.759 --> 00:23:15.599
<v Speaker 1>object can't just become a derived object.

476
00:23:15.640 --> 00:23:18.279
<v Speaker 2>No, there's no implicit conversion from base to derive, so

477
00:23:18.400 --> 00:23:21.079
<v Speaker 2>quote object doesn't have the discount information needed to be

478
00:23:21.079 --> 00:23:23.599
<v Speaker 2>a bulk quote. Slicing can occur if you try to

479
00:23:23.640 --> 00:23:26.759
<v Speaker 2>assign a derived object to a base object by value.

480
00:23:26.839 --> 00:23:30.599
<v Speaker 1>What about abstract base classes like disc quote with eto zero.

481
00:23:30.599 --> 00:23:34.759
<v Speaker 2>That includes zero makes a virtual function pure virtual. A

482
00:23:34.799 --> 00:23:37.640
<v Speaker 2>class with one or more pure virtual functions becomes an

483
00:23:37.680 --> 00:23:42.119
<v Speaker 2>abstract base class ABC. You cannot create objects directly from

484
00:23:42.119 --> 00:23:44.960
<v Speaker 2>an ABC. Its purpose is to define an interface that

485
00:23:45.079 --> 00:23:49.119
<v Speaker 2>concrete derived classes must implement. Any class inheriting from disc

486
00:23:49.160 --> 00:23:51.759
<v Speaker 2>quote has to provide its own net price implementation.

487
00:23:52.200 --> 00:23:57.000
<v Speaker 1>Access control also plays a role in inherence public protected, private, right.

488
00:23:56.839 --> 00:23:59.680
<v Speaker 2>Public inheritance Class D public B is the most common

489
00:23:59.759 --> 00:24:03.680
<v Speaker 2>for is A relationships Public members of B stay public,

490
00:24:03.680 --> 00:24:07.160
<v Speaker 2>in D protected stay protected. Protected inheritance makes public and

491
00:24:07.160 --> 00:24:11.119
<v Speaker 2>protected members of B become protected. In D private inheritance

492
00:24:11.160 --> 00:24:14.160
<v Speaker 2>makes them all private, and D private Protected inheritance are

493
00:24:14.160 --> 00:24:17.400
<v Speaker 2>more about implementationary use than interface inheritance and the crucial

494
00:24:17.480 --> 00:24:20.599
<v Speaker 2>rule about destructors virtual destructors. If a class is intended

495
00:24:20.599 --> 00:24:22.920
<v Speaker 2>to be a base class in an inheritance hierarchy, and

496
00:24:23.000 --> 00:24:25.400
<v Speaker 2>you might delete objects through a base class pointer, the

497
00:24:25.400 --> 00:24:27.599
<v Speaker 2>base class destructor must be declared virtual.

498
00:24:27.759 --> 00:24:28.839
<v Speaker 1>Why is that so critical?

499
00:24:29.039 --> 00:24:31.119
<v Speaker 2>Because if you delete a quote that points to a

500
00:24:31.119 --> 00:24:34.759
<v Speaker 2>bulk quote object and the quote destructor isn't virtual only

501
00:24:34.799 --> 00:24:37.799
<v Speaker 2>the quote destructor runs, the bulk quote part of the

502
00:24:37.799 --> 00:24:41.759
<v Speaker 2>object is never properly destroyed, leading to resource leaks. A

503
00:24:41.839 --> 00:24:46.599
<v Speaker 2>virtual destructor ensures the most derived destructor quotes runs first,

504
00:24:46.960 --> 00:24:50.000
<v Speaker 2>then the base quotes. It's essential for correctness.

505
00:24:50.119 --> 00:24:52.079
<v Speaker 1>Names can also be hidden in inheritance.

506
00:24:52.440 --> 00:24:55.880
<v Speaker 2>Yes, if a derived class declares a member function or

507
00:24:55.960 --> 00:24:58.519
<v Speaker 2>variable with the same name as one in the base class.

508
00:24:58.880 --> 00:25:01.759
<v Speaker 2>The derived class name hides the base class name within

509
00:25:01.799 --> 00:25:05.359
<v Speaker 2>the derived class's scope. For non virtual functions, calls a

510
00:25:05.440 --> 00:25:08.440
<v Speaker 2>resolve based on static type, so hiding can be confusing.

511
00:25:09.039 --> 00:25:12.480
<v Speaker 2>The using declaration, for example, using based dot funk inside

512
00:25:12.480 --> 00:25:15.640
<v Speaker 2>derived can bring hidden base class names back into scope,

513
00:25:15.960 --> 00:25:18.880
<v Speaker 2>especially useful for bringing all overloaded versions of a base

514
00:25:18.920 --> 00:25:20.440
<v Speaker 2>function into the derived scope.

515
00:25:20.680 --> 00:25:24.319
<v Speaker 1>The basket class example sounds pretty sophisticated. Using std dot

516
00:25:24.400 --> 00:25:26.680
<v Speaker 1>multiset with shared PDRs, Yeah.

517
00:25:26.440 --> 00:25:30.039
<v Speaker 2>That's a good example of managing a collection of polymorphic objects.

518
00:25:30.599 --> 00:25:34.079
<v Speaker 2>It uses stz dot shared ptr quote, so the multiset

519
00:25:34.119 --> 00:25:37.279
<v Speaker 2>can hold pointers to different kinds of quote objects bulk quote,

520
00:25:37.279 --> 00:25:41.200
<v Speaker 2>et cetera, without slicing. It probably uses a custom comparison

521
00:25:41.240 --> 00:25:44.160
<v Speaker 2>function for the multiset based on the shared PTRs, and

522
00:25:44.200 --> 00:25:47.200
<v Speaker 2>the aditum function likely uses a clone pattern, a virtual

523
00:25:47.200 --> 00:25:50.440
<v Speaker 2>function that creates a copy of the specific derived object

524
00:25:50.680 --> 00:25:53.880
<v Speaker 2>to safely add new items without knowing their exact type, and.

525
00:25:53.839 --> 00:25:56.920
<v Speaker 1>The query system hides a complex hierarchy exactly.

526
00:25:57.079 --> 00:26:00.559
<v Speaker 2>That's the power of abstraction. You have this underlying structure.

527
00:26:00.720 --> 00:26:04.160
<v Speaker 2>Query base and query or query et cetera, representing complex

528
00:26:04.240 --> 00:26:07.599
<v Speaker 2>logical combinations of search terms, but the user interacts only

529
00:26:07.640 --> 00:26:10.240
<v Speaker 2>through the simple query interface class. They can write things

530
00:26:10.240 --> 00:26:14.000
<v Speaker 2>like query A and query B, query C using overloaded operators,

531
00:26:14.200 --> 00:26:16.720
<v Speaker 2>and the interface class manages the creation and linking of

532
00:26:16.759 --> 00:26:19.839
<v Speaker 2>the underlying query objects. It makes a complex system easy

533
00:26:19.880 --> 00:26:20.200
<v Speaker 2>to use.

534
00:26:20.319 --> 00:26:23.960
<v Speaker 1>SOAP and C plus plus is really about managing complexity

535
00:26:24.000 --> 00:26:25.480
<v Speaker 1>and building flexible.

536
00:26:25.039 --> 00:26:29.400
<v Speaker 2>Extensible designs precisely virtual functions inheritance smart pointers. They are

537
00:26:29.480 --> 00:26:31.880
<v Speaker 2>key tools for large scale software development.

538
00:26:32.200 --> 00:26:36.559
<v Speaker 1>Let's switch to generic programming with templates. Reusability is the

539
00:26:36.640 --> 00:26:37.559
<v Speaker 1>name of the game here.

540
00:26:37.759 --> 00:26:41.960
<v Speaker 2>Absolutely function templates like template type name t int compare

541
00:26:42.200 --> 00:26:45.599
<v Speaker 2>CONSTNV one, CONSTNV two let you write a single function

542
00:26:45.680 --> 00:26:48.960
<v Speaker 2>definition that works for many different types T. The compiler

543
00:26:49.079 --> 00:26:51.960
<v Speaker 2>generates the specific version needed based on how you call

544
00:26:52.000 --> 00:26:53.519
<v Speaker 2>it template instantiation.

545
00:26:53.680 --> 00:26:55.279
<v Speaker 1>The compiler usually figures.

546
00:26:54.920 --> 00:26:59.119
<v Speaker 2>Out T often yes through template argument deduction, but sometimes

547
00:26:59.119 --> 00:27:02.039
<v Speaker 2>you need to specify but it explicitly like compare along

548
00:27:02.200 --> 00:27:04.720
<v Speaker 2>going ten twenty four. Maybe if deduction fails or you

549
00:27:04.759 --> 00:27:09.160
<v Speaker 2>need a specific conversion. When you specify arguments explicitly, normal

550
00:27:09.160 --> 00:27:10.920
<v Speaker 2>function argument conversions.

551
00:27:10.440 --> 00:27:12.920
<v Speaker 1>Can apply, and you can have class templates too, YEP.

552
00:27:13.319 --> 00:27:17.000
<v Speaker 2>Template type name T class blob defines a class template.

553
00:27:17.160 --> 00:27:20.200
<v Speaker 2>You can then create specific types like blobbin or blob

554
00:27:20.200 --> 00:27:23.119
<v Speaker 2>string std dot vector t is a classic example of

555
00:27:23.160 --> 00:27:23.920
<v Speaker 2>a class template.

556
00:27:24.000 --> 00:27:25.240
<v Speaker 1>What about veriatic templates?

557
00:27:25.720 --> 00:27:28.960
<v Speaker 2>Those are really powerful. They let you write templates functions

558
00:27:29.000 --> 00:27:32.400
<v Speaker 2>or classes that accept a variable number of template arguments

559
00:27:32.400 --> 00:27:36.039
<v Speaker 2>of potentially different types. Think of print or a function

560
00:27:36.119 --> 00:27:38.759
<v Speaker 2>that needs to process a list of arguments without knowing

561
00:27:38.799 --> 00:27:41.240
<v Speaker 2>how many there will be at compile time. The size

562
00:27:41.240 --> 00:27:43.480
<v Speaker 2>of operator tells you how many arguments were passed in

563
00:27:43.519 --> 00:27:44.000
<v Speaker 2>the pack.

564
00:27:44.039 --> 00:27:47.559
<v Speaker 1>And template specialization when the generic version.

565
00:27:47.559 --> 00:27:51.519
<v Speaker 2>Isn't right exactly. Sometimes the general template logic doesn't work

566
00:27:51.559 --> 00:27:54.559
<v Speaker 2>well for a specific type. A common example is comparing

567
00:27:54.720 --> 00:27:58.799
<v Speaker 2>C style strings constantar. The generic comparer might just compare

568
00:27:58.839 --> 00:28:02.240
<v Speaker 2>pointer addresses, which is useful. You can provide a template

569
00:28:02.279 --> 00:28:06.599
<v Speaker 2>specialization specifically for constchart that uses straight nep internally.

570
00:28:06.880 --> 00:28:10.559
<v Speaker 1>So templates give you massive code reuse and flexibility.

571
00:28:10.559 --> 00:28:13.720
<v Speaker 2>They're fundamental to modern C plus plus and the standard library.

572
00:28:13.799 --> 00:28:17.200
<v Speaker 2>They let you write type safe, highly optimized generic code.

573
00:28:16.960 --> 00:28:20.240
<v Speaker 1>Okay, robustness error handling things go wrong. How does C

574
00:28:20.319 --> 00:28:21.359
<v Speaker 1>plus plus handle that?

575
00:28:21.480 --> 00:28:25.559
<v Speaker 2>Primarily through exceptions. You use a triblock to enclose code

576
00:28:25.559 --> 00:28:28.599
<v Speaker 2>that might throw an exception. If an error occurs, code

577
00:28:28.640 --> 00:28:32.039
<v Speaker 2>can throw an exception object often derived from std dot

578
00:28:32.079 --> 00:28:33.920
<v Speaker 2>exception like std dot, run.

579
00:28:33.839 --> 00:28:36.480
<v Speaker 1>A terror and then catch blocks handle it right.

580
00:28:36.759 --> 00:28:39.960
<v Speaker 2>After the triblock. You have one or more catch blocks.

581
00:28:40.400 --> 00:28:43.240
<v Speaker 2>Each catch specifies the type of exception it can handle.

582
00:28:43.839 --> 00:28:47.000
<v Speaker 2>If an exception is thrown, the program unwinds the stack

583
00:28:47.160 --> 00:28:50.680
<v Speaker 2>looking for a matching catch block. This separates error handling

584
00:28:50.759 --> 00:28:53.039
<v Speaker 2>logic cleanly from the main program flow.

585
00:28:53.240 --> 00:28:55.000
<v Speaker 1>What about variables declared in the.

586
00:28:54.920 --> 00:28:57.759
<v Speaker 2>Triblock, they're out of scope in the catch blocks. If

587
00:28:57.799 --> 00:29:00.440
<v Speaker 2>you need to access something in both, declare it before the.

588
00:29:00.480 --> 00:29:03.119
<v Speaker 1>Dry block and the no except keyword no.

589
00:29:03.240 --> 00:29:05.480
<v Speaker 2>Accept is a specification you can add to a function

590
00:29:05.559 --> 00:29:09.359
<v Speaker 2>declaration void funk no accept is a promise that funk

591
00:29:09.359 --> 00:29:12.160
<v Speaker 2>will not throw any exceptions. If it does throw, the

592
00:29:12.200 --> 00:29:16.039
<v Speaker 2>program typically terminates immediately. It helps the compiler optimize and

593
00:29:16.119 --> 00:29:19.559
<v Speaker 2>signals intent to callers. Good error handling is crucial for

594
00:29:19.640 --> 00:29:20.880
<v Speaker 2>a liability as.

595
00:29:20.759 --> 00:29:24.839
<v Speaker 1>Projects get bigger. Organization is key. Name spaces help avoid

596
00:29:24.920 --> 00:29:25.640
<v Speaker 1>name clashes.

597
00:29:26.039 --> 00:29:28.920
<v Speaker 2>Yes, that's their main job. If you're using two different

598
00:29:29.000 --> 00:29:32.240
<v Speaker 2>libraries that both define a function called in it. Name

599
00:29:32.279 --> 00:29:37.200
<v Speaker 2>spaces prevent collision. You wrap your code in namespace my library.

600
00:29:37.279 --> 00:29:39.240
<v Speaker 1>They create separate scopes exactly.

601
00:29:39.559 --> 00:29:42.039
<v Speaker 2>To use something from a name space, you either qualify

602
00:29:42.039 --> 00:29:45.240
<v Speaker 2>the name my library dot in it, use it using

603
00:29:45.279 --> 00:29:48.480
<v Speaker 2>declaration using mylbrary dot in it, which brings just that

604
00:29:48.599 --> 00:29:52.079
<v Speaker 2>one name into the current scope, or a using directive

605
00:29:52.680 --> 00:29:54.400
<v Speaker 2>using namespace my library and.

606
00:29:54.359 --> 00:29:57.240
<v Speaker 1>The directive using namespace is sometimes frowned upon.

607
00:29:57.480 --> 00:30:01.480
<v Speaker 2>Yeah, especially using namespace SDD and files or at global

608
00:30:01.519 --> 00:30:04.119
<v Speaker 2>scope in source files, it dumps all the names from

609
00:30:04.160 --> 00:30:07.240
<v Speaker 2>the name space into your current scope, potentially reintroducing the

610
00:30:07.319 --> 00:30:10.440
<v Speaker 2>name collision problems. Name spaces were meant to solve. Using

611
00:30:10.440 --> 00:30:13.759
<v Speaker 2>declarations are generally safer as they only introduce specific names

612
00:30:13.759 --> 00:30:17.480
<v Speaker 2>you need. Directives are okay inside limited scopes like functions,

613
00:30:17.480 --> 00:30:18.200
<v Speaker 2>sometimes so.

614
00:30:18.279 --> 00:30:20.759
<v Speaker 1>Name spaces are essential for managing large code.

615
00:30:20.559 --> 00:30:24.119
<v Speaker 2>Bases, indispensable for modularity and preventing conflicts.

616
00:30:24.400 --> 00:30:27.119
<v Speaker 1>Finally, the source mentions some specialized library features.

617
00:30:27.279 --> 00:30:30.200
<v Speaker 2>Bit set yeah, SDD dot bitst is great for fixed

618
00:30:30.200 --> 00:30:33.920
<v Speaker 2>size sequences of bits, efficient storage, and bitwise operations. You

619
00:30:33.920 --> 00:30:36.359
<v Speaker 2>can initialize it from an integer or even a string

620
00:30:36.400 --> 00:30:37.480
<v Speaker 2>of zeros and ones.

621
00:30:37.599 --> 00:30:42.440
<v Speaker 1>Regular expressions rejects, very powerful pattern matching and text the sources.

622
00:30:42.480 --> 00:30:45.799
<v Speaker 1>Example of finding violations of I before E except after

623
00:30:45.880 --> 00:30:49.960
<v Speaker 1>C with rejects CI is cool. Std dot rejects st

624
00:30:50.079 --> 00:30:53.319
<v Speaker 1>dot smatch, and iterators like s reject exertor that you

625
00:30:53.400 --> 00:30:56.039
<v Speaker 1>find mash and replace complex patterns.

626
00:30:55.680 --> 00:30:56.599
<v Speaker 2>And random numbers.

627
00:30:56.960 --> 00:30:59.799
<v Speaker 1>C plus plus has a sophisticated random number library. Now

628
00:31:01.200 --> 00:31:04.279
<v Speaker 1>you use an engine like std dot defaultrum engine to

629
00:31:04.359 --> 00:31:08.519
<v Speaker 1>generate raw random numbers and a distribution like std dot

630
00:31:08.640 --> 00:31:12.000
<v Speaker 1>Uniform and Distribution or std dot normal distribution to shape

631
00:31:12.039 --> 00:31:14.640
<v Speaker 1>those numbers into the range and pattern you need, much

632
00:31:14.680 --> 00:31:15.880
<v Speaker 1>better than the old c rants.

633
00:31:15.920 --> 00:31:19.079
<v Speaker 2>So these are specialized tools for specific jobs, exactly.

634
00:31:18.799 --> 00:31:21.559
<v Speaker 1>Powerful additions to the standard library for when you need them.

635
00:31:21.640 --> 00:31:25.319
<v Speaker 2>Well, that's quite a journey from compiling Hello World to templates, OOP,

636
00:31:25.519 --> 00:31:28.720
<v Speaker 2>smart pointers and these specialized tools. It really covers a

637
00:31:28.720 --> 00:31:31.599
<v Speaker 2>lot of ground. We went from the absolute basics of

638
00:31:31.680 --> 00:31:36.480
<v Speaker 2>compilation and execution, through building custom types with classes, managing

639
00:31:36.559 --> 00:31:40.440
<v Speaker 2>data with containers and iterators, understanding the critical role of

640
00:31:40.480 --> 00:31:42.359
<v Speaker 2>memory management and smart.

641
00:31:42.079 --> 00:31:46.960
<v Speaker 1>Pointers, diving into object oriented design with inheritance and virtual functions,

642
00:31:47.359 --> 00:31:52.079
<v Speaker 1>leveraging generic programming with templates, and finally handling errors and

643
00:31:52.240 --> 00:31:53.160
<v Speaker 1>organizing code.

644
00:31:53.319 --> 00:31:56.279
<v Speaker 2>It's a good overview pulled from that source material, highlighting

645
00:31:56.319 --> 00:31:58.960
<v Speaker 2>those key concepts and hopefully some of the surprising or

646
00:31:59.000 --> 00:31:59.640
<v Speaker 2>tricky bits.

647
00:31:59.799 --> 00:32:03.000
<v Speaker 1>Yeah. C plus plus definitely has that reputation for being challenging,

648
00:32:03.279 --> 00:32:06.200
<v Speaker 1>but maybe its real power isn't just the low level control,

649
00:32:06.480 --> 00:32:09.400
<v Speaker 1>but how it forces you to think really deeply about

650
00:32:09.400 --> 00:32:11.920
<v Speaker 1>how computers work, how you structure solutions.

651
00:32:12.039 --> 00:32:14.880
<v Speaker 2>That's a great point. Every choice passed by a value

652
00:32:15.000 --> 00:32:17.839
<v Speaker 2>or reference, vector or array, virtual or not has a

653
00:32:17.880 --> 00:32:20.960
<v Speaker 2>precise impact. There's an elegance to that precision. When you

654
00:32:20.960 --> 00:32:23.759
<v Speaker 2>start to master it, it feels like crafting something intricate

655
00:32:23.839 --> 00:32:25.079
<v Speaker 2>and reliable.

656
00:32:24.880 --> 00:32:28.359
<v Speaker 1>Like a finely tuned machine. So here's something for you,

657
00:32:28.440 --> 00:32:32.079
<v Speaker 1>our listener, to think about. Reflecting on all these concepts,

658
00:32:32.240 --> 00:32:35.680
<v Speaker 1>from the core mechanics to the advanced abstractions, what specific

659
00:32:35.759 --> 00:32:38.640
<v Speaker 1>problem maybe when you've been stuck on or thinking about,

660
00:32:38.920 --> 00:32:41.759
<v Speaker 1>will you tackle next armed with this deeper insight into

661
00:32:41.920 --> 00:32:44.240
<v Speaker 1>CLUS plus intricate elegance.

662
00:32:44.640 --> 00:32:47.200
<v Speaker 2>Yeah, we'd definitely encourage you to dig into the original

663
00:32:47.240 --> 00:32:50.319
<v Speaker 2>source material if you can try applying these concepts, write

664
00:32:50.359 --> 00:32:53.079
<v Speaker 2>some code, and just keep exploring. C plus plus is

665
00:32:53.079 --> 00:32:55.039
<v Speaker 2>a language that rewards continuous learning,
