< Return to Video

Lecture 18 | Programming Abstractions (Stanford)

  • 0:00 - 0:08
  • 0:08 - 0:12
    This presentation is delivered by the Stanford Center for Professional
  • 0:12 - 0:16
    Development.
  • 0:22 - 0:26
    Okay. Well welcome, welcome. We got a couple parents who have braved the
  • 0:26 - 0:29
    other activities of Parents Weekend to come here, so thank you for coming to see what
  • 0:29 - 0:32
    it is that we do here in
  • 0:32 - 0:36
    CS106B. We are still in the process of grading the midterm. In fact, most of our grading, we're planning on
  • 0:36 - 0:40
    taking care of tomorrow, no, Sunday, in some big, massive grading sessions. So with any
  • 0:40 - 0:42
    luck, if it all goes well, we'll actually have them
  • 0:42 - 0:45
    ready to go back on Monday, but if somewhere it turns into some disaster, it may take us a
  • 0:45 - 0:48
    little longer, but hopefully. That's the plan.
  • 0:48 - 0:51
    So I'm gonna finish up a couple slides from last time,
  • 0:51 - 0:54
    and then I'm gonna mostly go on to do some code with you together.
  • 0:54 - 0:56
    But I just wanted to
  • 0:56 - 0:56
  • 0:56 - 1:00
    try to give you some perspective on the value of abstraction and the idea of an
  • 1:00 - 1:03
    abstract data type, or an ADT, and why
  • 1:03 - 1:07
    this is such a powerful and important concept in management of complexity.
  • 1:07 - 1:09
    So we saw this, for example,
  • 1:09 - 1:13
    in those first couple assignments that the client uses classes as
  • 1:13 - 1:14
    an abstraction.
  • 1:14 - 1:18
    You have the need to manage something that has a queue-like behavior: first in,
  • 1:18 - 1:19
    first out.
  • 1:19 - 1:23
    So what you want is something that you can put things in that will enforce that:
  • 1:23 - 1:26
    put things at the end of the line, always return to the head of the line.
  • 1:26 - 1:29
    And that how it managed what it did and what went on behind the scenes
  • 1:29 - 1:33
    wasn't something we had to worry about or even concern ourselves with. And in
  • 1:33 - 1:36
    fact, even if we wanted to, we couldn't muck around in there. Like
  • 1:36 - 1:39
    it wasn't our business, it was maintained privately.
  • 1:39 - 1:44
    And that is a real advantage for both sides, right? That the client
  • 1:44 - 1:47
    doesn't have to worry about it and can't even get in the way of us, that we
  • 1:47 - 1:50
    can work independently and get our things done.
  • 1:50 - 1:54
    And so one sort of piece of terminology we often use here, we talk about this wall of
  • 1:54 - 1:55
    abstraction.
  • 1:55 - 1:57
    That there is kind of a
  • 1:57 - 1:58
    real
  • 1:58 - 2:00
    block
  • 2:00 - 2:04
    that prevents the two of us from interfering with each other's process, as
  • 2:04 - 2:06
    part of, you know, combining to build a program together.
  • 2:06 - 2:10
    And there's a little tiny chink in that wall that we call the interface.
  • 2:10 - 2:13
    And that's the way that you speak to the stack and ask it to do things on your
  • 2:13 - 2:16
    behalf, and it listens to your requests and performs them.
  • 2:16 - 2:19
    And so if you think about the lexicon class, which we used in the Boggle and
  • 2:19 - 2:22
    in the recursion assignment that managed a word list,
  • 2:22 - 2:26
    the abstraction is, yeah, you say, ''Is this word in there? Add this word to it. Load
  • 2:26 - 2:29
    the words from a file.'' How does it store them? How does it do stuff? Did anybody
  • 2:29 - 2:33
    go open up the lexicon.cpp file just to see?
  • 2:33 - 2:34
    Anybody who was curious? And
  • 2:34 - 2:37
    what did you find out? I just -
  • 2:37 - 2:40
    I
  • 2:40 - 2:40
    think
  • 2:40 - 2:44
    it ended up in there [inaudible]. You ended up in there and when you got in there, what did you decide to do?
  • 2:44 - 2:45
    Leave. Leave.
  • 2:45 - 2:48
    Yeah. Did anybody else open it up and have the same sort of reaction? Over
  • 2:48 - 2:49
    here,
  • 2:49 - 2:54
    what did you think? I didn't really understand. Yeah. And what did you see? It was a mess. It was a mess. Who wrote that code? My, gosh, she should
  • 2:54 - 2:57
    be fired.
  • 2:57 - 3:00
    It's scary. It does something kind of scary. We'll talk about it. Actually, at the end, we'll come back here because I think it's actually
  • 3:00 - 3:02
    a really neat class to study.
  • 3:02 - 3:04
    But in fact, like you open it up and you're like,
  • 3:04 - 3:09
    ''I don't want to be here. I want to use a word list. Let me close this file and let me go back to word list. Add word,
  • 3:09 - 3:11
    contains word, okay.''
  • 3:11 - 3:14
    And you're happy about that. Right? It does something very complex that turns out to
  • 3:14 - 3:18
    be very efficient and optimize for the task at hand. But back to Boggle,
  • 3:18 - 3:20
    you don't want to be worrying about that; you got other things on your
  • 3:20 - 3:25
    plate and that's a fine place to just poke your nose right back out of. So if you haven't had a
  • 3:25 - 3:28
    chance to look at it, because we will talk about it later, but the person who wrote it,
  • 3:28 - 3:30
    was a crummy commoner. I'm just
  • 3:30 - 3:32
    saying
  • 3:32 - 3:36
    that they would definitely not be getting a check-plus on style, so.
  • 3:36 - 3:38
    So I drew this picture. It's like this wall. Right?
  • 3:38 - 3:42
    So when you made a lexicon, you say, ''Oh, I want a lexicon. Add this word. Add that word. Does it
  • 3:42 - 3:44
    contain this word?''
  • 3:44 - 3:47
    And that there is this big wall that - and you think of what's on the other side as a black box. The
  • 3:47 - 3:50
    black box is the microwave that you push buttons and food gets hot. How does
  • 3:50 - 3:53
    it really work? Ah, you know, who knows.
  • 3:53 - 3:55
    You don't open up the back. You don't dig around in it.
  • 3:55 - 3:58
    And this little chink here, that's the interface. And the
  • 3:58 - 4:01
    lexicon provides a very small interface, if you remember, adding the words, checking
  • 4:01 - 4:04
    contains word and prefix, reading
  • 4:04 - 4:07
    the words from a file, really not much else beyond that.
  • 4:07 - 4:11
    And then now what we're starting to think about is, ''Well, what's this other side look like?'' What goes over
  • 4:11 - 4:13
    here
  • 4:13 - 4:15
    is that there is this implementer
  • 4:15 - 4:18
    who does know the internal structure. Who does know what shenanigans are being
  • 4:18 - 4:21
    pulled on that inside, who does have access to that private data,
  • 4:21 - 4:25
    and who, upon request when you ask it add a word or look up a word or look up a
  • 4:25 - 4:29
    prefix, internally trolls through that private information and returns
  • 4:29 - 4:31
    information back to the client,
  • 4:31 - 4:35
    having mucked around in those internals. So when you say add a word,
  • 4:35 - 4:38
    maybe what its got is some array with a count of how many words are
  • 4:38 - 4:41
    used, and it sticks it in the next slot of the array
  • 4:41 - 4:43
    and updates its counter.
  • 4:43 - 4:46
    And we don't know what it does but it's not really our business as the client, but the
  • 4:46 - 4:47
    implementer has
  • 4:47 - 4:48
    kind of the full
  • 4:48 - 4:50
    picture of that.
  • 4:50 - 4:53
    And then over here on this side, if the client attempts to do the kind of things
  • 4:53 - 4:57
    that are really implementer specific, it tries to access directly the num words
  • 4:57 - 4:58
    and the words array
  • 4:58 - 5:01
    to go in and say, ''Yeah, I'd like to put pig in the array. How about I do this? How
  • 5:01 - 5:04
    about I change the number of words? Or how about I stick it in the slot at the beginning
  • 5:04 - 5:06
    and overwrite whatever's there.''
  • 5:06 - 5:09
    That an attempt to do this
  • 5:09 - 5:12
    should fail. It should not compile because these fields,
  • 5:12 - 5:14
    that are part of the lexicon,
  • 5:14 - 5:17
    should have been declared private to begin with,
  • 5:17 - 5:20
    to make sure that that wall's maintained. Everything that's private is like
  • 5:20 - 5:24
    over here on this side of the wall,
  • 5:24 - 5:27
    inaccessible outside of that. And
  • 5:27 - 5:30
    so why do we think this is important?
  • 5:30 - 5:34
    Of all the ideas that come away from 106B, I think this is one of the top
  • 5:34 - 5:38
    three is this idea of abstraction. We actually even call the whole class
  • 5:38 - 5:39
    Programming Abstractions.
  • 5:39 - 5:40
    Because
  • 5:40 - 5:45
    that the advantage of using this as a strategy for solving larger and
  • 5:45 - 5:49
    more complicated problems is that you can divide up your tasks.
  • 5:49 - 5:52
    That you can say this is an abstraction, like a word list, and kind of have it be as fancy as
  • 5:52 - 5:54
    it needs to be behind the scenes
  • 5:54 - 5:56
    but very easy to use from the outside.
  • 5:56 - 5:59
    So that makes it easy for me to write some piece and give it to you
  • 5:59 - 6:01
    in a form that's easy for you to incorporate.
  • 6:01 - 6:04
    We can work on our things without stepping on each other. As you get to
  • 6:04 - 6:06
    larger and larger projects
  • 6:06 - 6:07
    beyond this class,
  • 6:07 - 6:09
    you'll need ways of making it so three people can work together without
  • 6:09 - 6:12
    stepping on each other's toes the whole time. And classes provide a really good
  • 6:12 - 6:15
    way of managing those boundaries
  • 6:15 - 6:16
    to keep each other
  • 6:16 - 6:18
    out of each other's hair.
  • 6:18 - 6:21
    And there's a lot of flexibility
  • 6:21 - 6:24
    given to us by this. And we're gonna see this actually as we go forward, that we can talk
  • 6:24 - 6:25
    about what a vector is.
  • 6:25 - 6:29
    It keeps things in index order. Or a stack is, it does LIFO.
  • 6:29 - 6:30
    But there is no guarantee there about
  • 6:30 - 6:34
    how it internally is implemented, no guarantee expressed or implied, and
  • 6:34 - 6:37
    that actually gives you a lot of flexibility as the implementer.
  • 6:37 - 6:40
    You can decide to do it one way today, and if upon later learning about some
  • 6:40 - 6:43
    other new technique or some way to save memory or time,
  • 6:43 - 6:45
    you can swap it out,
  • 6:45 - 6:47
    replace an implementation with something better,
  • 6:47 - 6:51
    and all the code that depends on it shouldn't require any changes.
  • 6:51 - 6:54
    That suddenly add word just runs twice as fast or ten times as fast,
  • 6:54 - 6:57
    would be something everybody could appreciate without having to do anything in their own
  • 6:57 - 7:00
    code to take advantage of that.
  • 7:00 - 7:01
    So these are good things to know.
  • 7:01 - 7:05
    So what I'm gonna do actually today is I'm gonna just stop doing slides, because I'm sick of doing
  • 7:05 - 7:08
    slides. We do way too many slides; I'm bored with slides.
  • 7:08 - 7:11
    And what I'm gonna do is I'm gonna actually go through the process of
  • 7:11 - 7:13
    developing vector
  • 7:13 - 7:15
    from just the ground up.
  • 7:15 - 7:16
    So my plan here is to say
  • 7:16 - 7:17
    our goal is to make
  • 7:17 - 7:19
    the vector abstraction
  • 7:19 - 7:23
    real, so to get dirty, get behind the scenes and say we know what vector is. It
  • 7:23 - 7:24
    acts like an array. It
  • 7:24 - 7:26
    has these indexed
  • 7:26 - 7:29
    slots. It's this linear collection. It lets you put things anywhere you like in
  • 7:29 - 7:30
    the vector. We're gonna
  • 7:30 - 7:33
    go through the process of making that whole thing.
  • 7:33 - 7:35
    And I'm gonna start
  • 7:35 - 7:39
    at the - with a simple form that actually is not templatized and then I'm gonna
  • 7:39 - 7:42
    change it to one that is templatized. So we're gonna see kind of the whole process from
  • 7:42 - 7:44
    start to end. So
  • 7:44 - 7:48
    all I have are empty files right now. I have myvector.h and myvector.cpp that
  • 7:48 - 7:51
    really have sort of nothing other than sort of boilerplate stuff in them.
  • 7:51 - 7:54
    So let me look at myvector.h to start with.
  • 7:54 - 7:58
    So I'm calling this class myvector so that it doesn't confuse with the existing
  • 7:58 - 8:00
    vector class, so that we have that name there.
  • 8:00 - 8:05
    And I'm gonna start by just putting in
  • 8:05 - 8:06
    the
  • 8:06 - 8:09
    simple parts of the interface, and then we'll see how many other things we
  • 8:09 - 8:12
    have time to kind of add into it. But I'm gonna get the kinda basic skeletal functions
  • 8:12 - 8:15
    down and show how they get implemented, and then we'll see what else we'll try.
  • 8:15 - 8:19
    So having the size is probably pretty important, being able to say, ''Well how many things will I
  • 8:19 - 8:22
    put in there,'' get that back out,
  • 8:22 - 8:23
    being able to add an element.
  • 8:23 - 8:27
    And I'm gonna assume that right now the vector's gonna hold just scranks.
  • 8:27 - 8:29
    Certainly that's not what we're gonna want in the long run, but I'm just gonna pick something
  • 8:29 - 8:32
    for now so that we have something to practice with.
  • 8:32 - 8:36
    And then I'm gonna have the get at,
  • 8:36 - 8:38
    which give it an index and return something. Okay,
  • 8:38 - 8:41
    so I think these are the only ones I'm gonna have in the first version.
  • 8:41 - 8:47
    And then the other ones, you remember, there's like a remove at, there's an insert at,
  • 8:47 - 8:47
    there's an
  • 8:47 - 8:55
    overloaded bracket operator, and things like that I'm not gonna show right away. Question? [Inaudible]. Oh yeah, yeah. This is
  • 8:55 - 8:58
    actually you know kind of just standard boilerplate for C or C++
  • 8:58 - 9:01
    header files. And you'll see this again and again and again. I should really have pointed
  • 9:01 - 9:02
    this out at some point along the way
  • 9:02 - 9:08
    is that the compiler does not like to see two definitions of the same thing, ever.
  • 9:08 - 9:11
    Even if those definitions exactly match, it just gets its
  • 9:11 - 9:15
    total knickers in a twist about having seen a class myvector, another
  • 9:15 - 9:16
    class myvector.
  • 9:16 - 9:18
    And so if you
  • 9:18 - 9:21
    include the header file, myvector, one place and you include it some other place, it's gonna end up
  • 9:21 - 9:24
    thinking there's two myvectors classes out there and it's gonna have a problem.
  • 9:24 - 9:28
    So this little bit of boilerplate is to tell the compiler, ''If you haven't already
  • 9:28 - 9:32
    seen this header, now's the time to go in there.'' So this ifindex, if not
  • 9:32 - 9:34
    defined, and then the name there is something I made up, some symbol name
  • 9:34 - 9:36
    that's unique to this file. When I say,
  • 9:36 - 9:38
    ''Define that symbol,'' so
  • 9:38 - 9:41
    it's like saying, ''I've seen it,'' and then down here at the very bottom, there's an end if
  • 9:41 - 9:43
    that matches it. And so,
  • 9:43 - 9:44
    in the case where we have -
  • 9:44 - 9:47
    this is the first time we've seen the file it'll say, ''If not to define the symbol it's
  • 9:47 - 9:48
    not.''
  • 9:48 - 9:51
    It'll say, ''Define that symbol, see all this stuff, and then the end if.'' The second time
  • 9:51 - 9:54
    it gets here it'll say, ''If not define that symbol, say that symbol's already defined,'' so it'll skip
  • 9:54 - 9:59
    down to the end if. And so, every subsequent attempt to look at myvector
  • 9:59 - 10:00
    will be passed over.
  • 10:00 - 10:03
    If you don't have it, you'll get a lot of errors about,
  • 10:03 - 10:05
    ''I've seen this thing before. And it looks like the one I saw before but I don't like
  • 10:05 - 10:06
    it. You
  • 10:06 - 10:08
    know smells suspicious to me.''
  • 10:08 - 10:13
    So that is sort of standard boilerplate for any header file is to have this
  • 10:13 - 10:16
    multiple include protection on it. Anything else you
  • 10:16 - 10:18
    want to ask about the - way in the back? Why
  • 10:18 - 10:20
    would it look at it multiple times, though?
  • 10:20 - 10:23
    Well because sometimes you include it and sometimes - for example, think about genlib. Like I might
  • 10:23 - 10:25
    include genlib but then
  • 10:25 - 10:27
    I include something else that includes genlib. So there's these ways that
  • 10:27 - 10:29
    you could accidentally get in there more than once,
  • 10:29 - 10:32
    just because some other things depend on it, and the next thing you know. So
  • 10:32 - 10:34
    it's better to just have the header file never
  • 10:34 - 10:38
    complain about that, never let that happen, than to make it somebody else's responsibility
  • 10:38 - 10:44
    to make sure it never happened through the includes.
  • 10:44 - 10:45
    So I've got five
  • 10:45 - 10:48
    member functions here that I'm gonna have to implement.
  • 10:48 - 10:52
    And now I need to think about what the private data, this guy's gonna look like. So
  • 10:52 - 10:55
    now, we are the low-level implementer.
  • 10:55 - 10:58
    We're not building on anything else right now, because myvector is kind
  • 10:58 - 11:00
    of the bottommost piece of things here.
  • 11:00 - 11:05
    We've got nothing out there except for the raw array to do the job for us. So
  • 11:05 - 11:06
    typically, the most
  • 11:06 - 11:07
  • 11:07 - 11:08
    compatible
  • 11:08 - 11:12
    mechanism to map something like vector onto is the array. You know it has
  • 11:12 - 11:16
    contiguous memory, it allows you to do direct access to things by index,
  • 11:16 - 11:19
    and so that's where we're gonna start. And we'll come back and talk about that, whether
  • 11:19 - 11:23
    that's the only option we have here. But what I'm gonna put in here
  • 11:23 - 11:24
    is a pointer
  • 11:24 - 11:25
    to
  • 11:25 - 11:26
  • 11:26 - 11:27
    a string, or
  • 11:27 - 11:31
    in this case it's gonna be a pointer to a string
  • 11:31 - 11:34
    array. And so in C++ those both look the same, this says arr is a single pointer that points
  • 11:34 - 11:35
    to
  • 11:35 - 11:38
    a string in memory, which in our situation is actually gonna be a whole sequence
  • 11:38 - 11:41
    of strings in memory kind of one after another.
  • 11:41 - 11:44
    The array has no knowledge of its length
  • 11:44 - 11:47
    so we're gonna build is using new and things like that. It will not know how big it is.
  • 11:47 - 11:50
    It will be our job to manually track that.
  • 11:50 - 11:52
    So I'm gonna go ahead and have
  • 11:52 - 11:55
    two fields to go with it, and I'm gonna show you why I have two in a
  • 11:55 - 12:00
    minute. But instead of having just a length field that says the array is this long,
  • 12:00 - 12:02
    I'm actually gonna track two integers on it
  • 12:02 - 12:05
    because likely the thing I'm gonna do with the array is I'm gonna allocate it to a
  • 12:05 - 12:07
    certain size and then kind of fill it up.
  • 12:07 - 12:09
    And then when it gets
  • 12:09 - 12:13
    totally filled, then I'm gonna do a process of resizing it and enlarging it.
  • 12:13 - 12:15
    And so, at any given point, there may be
  • 12:15 - 12:18
    a little bit excess capacity, a little slack in the system. So we might start by
  • 12:18 - 12:20
    making it ten long
  • 12:20 - 12:21
    and then fill it up,
  • 12:21 - 12:24
    and then as we get to size 10, make it 20 or something like that.
  • 12:24 - 12:27
    So at any point, we'll need to know things about that array: how many of
  • 12:27 - 12:31
    the slots are actually used, so that'll be the first five slots are in use; and then
  • 12:31 - 12:33
    the number of allocated will tell me how many other - how many
  • 12:33 - 12:37
    total slots do I have, so how many slots can I use before
  • 12:37 - 12:37
    I
  • 12:37 - 12:40
    will have run out of space.
  • 12:40 - 12:42
    Both of those. Okay,
  • 12:42 - 12:45
    so there's my interface. So these things all public because anybody can use
  • 12:45 - 12:46
    them;
  • 12:46 - 12:49
    these things private because they're gonna be part of my implementation; I don't want anybody mucking with
  • 12:49 - 12:50
    those
  • 12:50 - 12:53
    or directly accessing them at all,
  • 12:53 - 12:55
    so I put them down there. All
  • 12:55 - 12:57
    right, now I go to myvector.cpp.
  • 12:57 - 13:01
    So it includes myvector.h, so that it already has seen the class interface so it knows
  • 13:01 - 13:04
    when we're talking about when we start trying to implement methods on the myvector
  • 13:04 - 13:06
    class. And I'm
  • 13:06 - 13:07
    gonna start with
  • 13:07 - 13:10
    myvector's constructor,
  • 13:10 - 13:13
    and the goal of the constructor will be to setup the instance variables of this
  • 13:13 - 13:17
    object into a state that makes sense.
  • 13:17 - 13:18
    So what I'm gonna choose to do
  • 13:18 - 13:24
    is allocate my array to some size. I'm gonna pick ten. So
  • 13:24 - 13:28
    I'm gonna say I want space for ten strings.
  • 13:28 - 13:31
    I want to record that I made space for ten strings so I know the num
  • 13:31 - 13:33
    allocated, the size of my array right now is ten,
  • 13:33 - 13:37
    and the number used is zero.
  • 13:37 - 13:39
    So that means that when someone
  • 13:39 - 13:46
    makes a call, like a declaration, that says myvector V, so if I'm back over here in my main. Say
  • 13:46 - 13:49
    myvector V,
  • 13:49 - 13:54
    but the process of constructing that vector V will cause the constructor to get
  • 13:54 - 13:58
    called, will cause a ten-member string element array to get allocated out in the
  • 13:58 - 13:58
    heap
  • 13:58 - 14:01
    that's pointed to by arr, and then it will set those two integers to know that there's ten
  • 14:01 - 14:03
    of them and zero of them are used.
  • 14:03 - 14:07
    So just to kind of all as part of the machinery of declaring, the
  • 14:07 - 14:11
    constructor is just wired into that so we get setup, ready to go, with some empty
  • 14:11 - 14:16
    space set aside.
  • 14:16 - 14:18
    So to go with that, I'm
  • 14:18 - 14:22
    gonna go ahead and add the destructor right along side of it,
  • 14:22 - 14:26
    which is I need to be in charge of cleaning up my
  • 14:26 - 14:28
    dynamic allocation. I
  • 14:28 - 14:30
    allocated that with the new bracket,
  • 14:30 - 14:33
    the new that allocates out in the heap that uses the bracket form has a
  • 14:33 - 14:37
    matching delete bracket that says delete a whole array's worth of data, so not just
  • 14:37 - 14:40
    one string out there but a sequence of them.
  • 14:40 - 14:43
    We don't have to tell it the size; it actually does - as much as I said, it doesn't
  • 14:43 - 14:47
    its size. Well somewhere in the internals, it does know the size but it never
  • 14:47 - 14:49
    exposes it to us. So in fact, once I delete [inaudible] array,
  • 14:49 - 14:52
    it knows how much space is there to cleanup. Yeah?
  • 14:52 - 14:54
    Are you just temporarily
  • 14:54 - 14:58
    setting it up so the vector only works on strings? Yes, we are. Okay. Yes. We're gonna
  • 14:58 - 14:59
    come back and fix that, but
  • 14:59 - 15:02
    I think it's easier maybe to see it one time on a fixed type and then say, ''Well, what happens when you
  • 15:02 - 15:05
    go to template? What things change?'' And we'll see all the places that we have to make
  • 15:05 - 15:08
    modifications.
  • 15:08 - 15:11
    So I have myvector
  • 15:11 - 15:13
    size.
  • 15:13 - 15:17
    Which variable's the one that tells us about size?
  • 15:17 - 15:20
    I got none used. I got none allocated. Which is the right one? Num
  • 15:20 - 15:24
    used. Num used, that is exactly right. So num allocated turned out to be something we only will
  • 15:24 - 15:29
    use internally. That's not gonna - no one's gonna see that or know about it, but it is -
  • 15:29 - 15:33
    the num used tracks how many elements have actually been put in there. Then
  • 15:33 - 15:35
    I write
  • 15:35 - 15:39
    myvector add.
  • 15:39 - 15:42
    So I'm gonna write one line of code, then I'm gonna come back and think about it for a
  • 15:42 - 15:44
    second. I could
  • 15:44 - 15:45
    say
  • 15:45 - 15:49
    arr num
  • 15:49 - 15:50
    used ++ = S, so tight little line that
  • 15:50 - 15:54
    has a lot of stuff wrapped up in it.
  • 15:54 - 15:55
    Using
  • 15:55 - 15:59
    the brackets on the dynamic array here are saying, ''Take the array
  • 15:59 - 16:03
    and right to the num used slot, post-incrementing it so it's a slide effect.'' So if
  • 16:03 - 16:08
    num used is zero to start with, this has the effect of saying array of,
  • 16:08 - 16:13
    and then the num used ++ returns the value before incrementing. So it evaluates to zero,
  • 16:13 - 16:17
    but as a slide effect the next use of num used will now be one. So that's exactly
  • 16:17 - 16:22
    what we want, we want to write the slot zero and then have num used be one in subsequent usage.
  • 16:22 - 16:25
    And then we assign that to be S, so it'll put it in the right spot of the array. So once num
  • 16:25 - 16:27
    used is five, so that
  • 16:27 - 16:31
    means the zero through four slots are used. It'll write to the fifth slot and then
  • 16:31 - 16:35
    up the num used to be six, so we'll know our size is now up by one.
  • 16:35 - 16:41
    What else does add need to do? Is it good? Needs to make sure that we have that [inaudible]. It'd
  • 16:41 - 16:43
    better
  • 16:43 - 16:44
    make sure we have some space.
  • 16:44 - 16:48
    So I'm gonna do this right now. I'm gonna say if num used
  • 16:48 - 16:50
    is equal to num allocated, I'm gonna raise an error. I'm
  • 16:50 - 16:56
    gonna come back to this but I'm gonna say -
  • 16:56 - 16:57
    or
  • 16:57 - 17:00
    for this first pass, we're gonna make it so it just doesn't grow. Picked some arbitrary size, it
  • 17:00 - 17:04
    got that big, and then it ran out of space. Question?
  • 17:04 - 17:07
    So when the - for the
  • 17:07 - 17:09
    vector zero, first time it gets called it's actually gonna
  • 17:09 - 17:11
    be placed in index one of the array?
  • 17:11 - 17:16
    So it's in place of index zero. So num used ++, any variable ++ returns the - it
  • 17:16 - 17:20
    evaluates to the value before it increments, and then as a side effect, kind of in the next
  • 17:20 - 17:23
    step, it will update the value. So there is a difference between
  • 17:23 - 17:26
    the ++ num used and the num ++ form.
  • 17:26 - 17:28
    Sometimes it's a little bit of an obscure detail we don't spend a lot of time on, but
  • 17:28 - 17:30
    ++ num says
  • 17:30 - 17:33
    first increment it and then tell me what the newly incremented value is.
  • 17:33 - 17:36
    Num ++ says tell me what the value is right now and then, as a side effect, increment it
  • 17:36 - 17:41
    for later use. So the num used gets changed in that? It does get changed in that expression, but the
  • 17:41 - 17:46
    expression happened to evaluate to the value before it did that change.
  • 17:46 - 17:49
    Question? And
  • 17:49 - 17:54
    is it really necessary to have myvector:: or is - Oh yeah, yeah, yeah, yeah. - there any way for - So if I take this out,
  • 17:54 - 17:55
    and I could show you what happens if I do
  • 17:55 - 17:59
    this, is what the compiler's gonna think that is, is it thinks, ''Oh, there's just a function
  • 17:59 - 18:03
    called size that take the arguments and returns them in.'' And it doesn't exist in any
  • 18:03 - 18:05
    context; it's just a global function.
  • 18:05 - 18:08
    And then I try to compile it, if I go ahead and do it,
  • 18:08 - 18:11
    it's gonna say, ''Num used? What's num used? Where did num used come from?''
  • 18:11 - 18:14
    So if I click on this it'll say, ''Yeah, num used was not declared in this scope.'' It has no idea where that
  • 18:14 - 18:18
    came from. So there is no mechanism in C++ to identify this as being a
  • 18:18 - 18:21
    member function other than scoping it with the right names. You say this is
  • 18:21 - 18:23
    the size
  • 18:23 - 18:25
    function
  • 18:25 - 18:27
    that is part of the myvector class. And now
  • 18:27 - 18:31
    it has the right context to interpret that and it knows that when you talk about num used,
  • 18:31 - 18:34
    ''Oh, there's a private data member that matches that. That must be the receiver's
  • 18:34 - 18:37
    num used.'' So
  • 18:37 - 18:38
    one other
  • 18:38 - 18:42
    member function we got to go,
  • 18:42 - 18:45
    which is the one that returns,
  • 18:45 - 18:47
    of I do this,
  • 18:47 - 18:49
    it almost but not quite,
  • 18:49 - 18:51
    looks like what I wanted. So I
  • 18:51 - 18:53
    say return arrays of index.
  • 18:53 - 18:56
    They said get in the next and returned the string that was at that index.
  • 18:56 - 19:03
    Is there anything else I might want to do here? Check and see if the index is [inaudible]. Well, let me
  • 19:03 - 19:05
    check and see if that index is valid.
  • 19:05 - 19:06
    Now, this is one of those cases where it's like you
  • 19:06 - 19:10
    could just sort of take the stance that says, ''Well, it's not my job.'' If you ask me to get you
  • 19:10 - 19:14
    know something at index 25, and there are only four of them, that's your own fault and you
  • 19:14 - 19:14
    deserve
  • 19:14 - 19:16
    what you get.
  • 19:16 - 19:18
    And that is certainly
  • 19:18 - 19:21
    the way a lot of professional libraries work because this, if I added a step here
  • 19:21 - 19:24
    that does a check, it means that every check costs a little bit more.
  • 19:24 - 19:26
    When you go in to get something out of the vector, it's gonna have to look and
  • 19:26 - 19:28
    make sure you were doing it correctly.
  • 19:28 - 19:31
    And there are people who believe that if it's like riding a motorcycle without a helmet,
  • 19:31 - 19:32
    that's your own
  • 19:32 - 19:33
    choice.
  • 19:33 - 19:35
    We're gonna actually bullet proof;
  • 19:35 - 19:36
    we're gonna make sure
  • 19:36 - 19:39
    that the index
  • 19:39 - 19:41
    isn't whack.
  • 19:41 - 19:45
    And I'm gonna go ahead and use my own size there. I'm gonna say if the index is less zero or it's greater
  • 19:45 - 19:47
    than or equal to, and I'm gonna use size.
  • 19:47 - 19:52
    I could use num used there but there are also reasons that if I use my own member functions
  • 19:52 - 19:55
    and then later somehow I change that name or I change how I calculate the
  • 19:55 - 19:59
    size, let's say I change it to where I use a linked list within an array and I'm managing the size
  • 19:59 - 20:00
    differently,
  • 20:00 - 20:03
    that if I have used size in this context, it will just change along with that
  • 20:03 - 20:06
    because it's actually depending on the
  • 20:06 - 20:08
    other part of the interface that I'll update.
  • 20:08 - 20:09
    And so I'm gonna go ahead and do that
  • 20:09 - 20:12
    rather than directly asking my variable. I'll say if that happens I say error, out of bounds.
  • 20:12 - 20:15
    And on
  • 20:15 - 20:18
    that, that error will cause the program to halt right down there, so I don't have to worry about
  • 20:18 - 20:21
    it, in that case, getting down to the return. So I feel
  • 20:21 - 20:22
    okay about this.
  • 20:22 - 20:25
    Not too much code to get kind of a little bit of something up and
  • 20:25 - 20:26
    running here.
  • 20:26 - 20:39
    Let's go over and write something to test. Add Jason, and here we go. Okay, so I
  • 20:39 - 20:41
    put some things in there and I'm
  • 20:41 - 20:43
    gonna see if
  • 20:43 - 20:50
    it'll let me get them back out.
  • 20:50 - 20:51
    And
  • 20:51 - 20:54
    before I get any further, I might as well test the code I have. Right?
  • 20:54 - 20:58
    This is - one of the things about designing a class is it's pretty hard to write
  • 20:58 - 21:02
    any one piece and test it by itself because often there's a relationship: the constructor
  • 21:02 - 21:04
    and then some adding and then some getting stuff back out.
  • 21:04 - 21:07
    So it's a little bit more code than I typically would like to write and not have
  • 21:07 - 21:10
    a chance to test, having all five of these member functions kind of at first.
  • 21:10 - 21:11
    So
  • 21:11 - 21:14
    if I run this test and it doesn't work, it's like well which part what was wrong? Was the
  • 21:14 - 21:17
    constructor wrong? Was the add wrong? Was the size wrong? You know there's a bunch of
  • 21:17 - 21:19
    places to look, but
  • 21:19 - 21:22
    unfortunately, they're kind of all interrelated in a way that makes it a little hard to have them
  • 21:22 - 21:23
    independently
  • 21:23 - 21:26
    worked out. But then subsequent thing, hopefully I can add the like the
  • 21:26 - 21:28
    insert at method without
  • 21:28 - 21:33
    having to add a lot more before I test.
  • 21:33 - 21:37
    Okay. So I run this guy and it says Jason, Illia, Nathan. Feel good, I feel good,
  • 21:37 - 21:41
    I feel smart.
  • 21:41 - 21:42
    Put them in, in that order. See
  • 21:42 - 21:44
    me get them out in that order. I might
  • 21:44 - 21:46
    try some things that I'm hoping will cause my thing
  • 21:46 - 21:48
    to blow up.
  • 21:48 - 21:53
    Why don't I get at ten? Let's see, I
  • 21:53 - 21:55
    like to be sure,
  • 21:55 - 21:59
    so I want you to tell me what's at the tenth slot in that vector.
  • 21:59 - 22:02
    And it's, ooh, out of bounds, just like I was hoping for.
  • 22:02 - 22:05
    Oh, I like to see that. Right?
  • 22:05 - 22:07
    What happens if I put
  • 22:07 - 22:10
    in
  • 22:10 - 22:11
    enough strings
  • 22:11 - 22:12
    that I
  • 22:12 - 22:16
    run out of memory? And we talked about a thing - it's set it to be ten right now. Why don't I just make it
  • 22:16 - 22:19
    smaller, that'll way it'll make it easier for me. So I say, ''Oh how
  • 22:19 - 22:21
    about this?'' I'm
  • 22:21 - 22:23
    only gonna make
  • 22:23 - 22:26
    space for two things. And it just:
  • 22:26 - 22:30
    error, out of space. Right? That happened before it got to printing anything. It tried to add the first one. It
  • 22:30 - 22:33
    added the second one. Then it went to add that third one and it said, ''Oh okay, we run out of space. We
  • 22:33 - 22:35
    only had space for two set aside, you
  • 22:35 - 22:40
    asked me to put a third in. I had no room.''
  • 22:40 - 22:42
    So at least the kind of simple behaviors that I put in here seem to kind of
  • 22:42 - 22:46
    show evidence that we've got a little part of this up and running.
  • 22:46 - 22:48
    What I'm gonna fix first is this out of space thing.
  • 22:48 - 22:54
    So it would be pretty bogus and pretty unusual for a
  • 22:54 - 22:56
    collection class like this to have some sort of fixed limit.
  • 22:56 - 22:59
    Right? It wouldn't - you know it'd be very unusual to say well it's always gonna hold exactly 10
  • 22:59 - 23:02
    things or 100 things or even a 1,000 things. Right?
  • 23:02 - 23:05
    You know one way you might design it is you could imagine adding an
  • 23:05 - 23:07
    argument to the constructor that said, ''Well, how many things do you plan on putting in
  • 23:07 - 23:11
    there? And then I'll allocate it to that. And then when we run out of space, you know you're hosed.''
  • 23:11 - 23:14
    But certainly a better strategy that kind of solves more general case problems would
  • 23:14 - 23:16
    be like, ''Oh let's grow.
  • 23:16 - 23:20
    When we run out of space, let's make some more space.'' Okay,
  • 23:20 - 23:23
    let's think about what it takes to make more space in
  • 23:23 - 23:24
    using pointers.
  • 23:24 - 23:31
    So what a vector really looks like
  • 23:31 - 23:33
    is it has three fields,
  • 23:33 - 23:34
    the arr,
  • 23:34 - 23:39
    the num used, and the num allocated. When
  • 23:39 - 23:43
    I declare one, the way it's being setup right now, it's over here and it's allocating space
  • 23:43 - 23:45
    for
  • 23:45 - 23:47
    some number, let's say it's ten again,
  • 23:47 - 23:48
    and then marking it as zero.
  • 23:48 - 23:53
    Then as it fills these things up, it puts strings in each of these slots and it
  • 23:53 - 23:58
    starts updating this number, eventually it gets to where all of them are filled.
  • 23:58 - 24:02
    That when num used equals num allocated, it means that however much space I set
  • 24:02 - 24:05
    aside, every one of those slots is now in use.
  • 24:05 - 24:08
    So when that happens, it's gonna be time to make a bigger array.
  • 24:08 - 24:11
    There is not a mechanism in C++ that says take my array and just make
  • 24:11 - 24:13
    it bigger where it is.
  • 24:13 - 24:16
    That the way we'll have to do this is, we'll have to make a bigger array, copy over
  • 24:16 - 24:17
    what we have,
  • 24:17 - 24:18
    and then,
  • 24:18 - 24:22
    you know, have it add it on by making a bigger array full of space. So what we'll do is we'll make
  • 24:22 - 24:23
    something that's like
  • 24:23 - 24:27
    twice as big, I'm just gonna draw it this way since I'm running out of board space,
  • 24:27 - 24:31
    and it's got ten slots and then ten more. And
  • 24:31 - 24:36
    then I will copy over all these guys that I have
  • 24:36 - 24:38
    up to the end,
  • 24:38 - 24:40
    and then I have these new spaces at the end.
  • 24:40 - 24:41
    And so I will have
  • 24:41 - 24:44
    to reset my pointer to point to there,
  • 24:44 - 24:49
    update my num allocated, let's say to be twice as big or something,
  • 24:49 - 24:52
    and then delete this old region that
  • 24:52 - 24:54
    I'm no longer using.
  • 24:54 - 24:57
    So we're gonna see an allocate, a copy, a delete,
  • 24:57 - 25:00
    and then kind of resetting our fields
  • 25:00 - 25:01
    to know what we just did.
  • 25:01 - 25:05
    So I'm gonna make a private helper to do all this, and
  • 25:05 - 25:12
    I'll just call that enlarge capacity here. Question? Is this like [inaudible]? Well
  • 25:12 - 25:14
    it is - it can be, is the truth.
  • 25:14 - 25:16
    So you're getting a little
  • 25:16 - 25:18
    bit ahead of us. But in the sense that like,
  • 25:18 - 25:20
    you know, if the array has a thousand elements
  • 25:20 - 25:23
    and now we got to put that thousand-first thing in, it's gonna take
  • 25:23 - 25:26
    all thousand and copy them over and enlarge the space.
  • 25:26 - 25:30
    So in effect what is typically an O of one operation, just tacking something on
  • 25:30 - 25:34
    the end, every now and then is gonna take a whole hit of an end
  • 25:34 - 25:37
    operation when it does the copy. But
  • 25:37 - 25:39
    one way to think about that is that is
  • 25:39 - 25:42
    every now it's really expensive but kind of if you think of it across the whole
  • 25:42 - 25:45
    space, that you got a - let's say you started at 1,000 and then you
  • 25:45 - 25:46
    doubled to 2,000, that
  • 25:46 - 25:48
    the first 1,000 never paid that cost.
  • 25:48 - 25:51
    And then all of a sudden one of them paid it but then now you don't pay it again for
  • 25:51 - 25:55
    another 1,000. But if you kind of divided that cost, sort of amortized it across all
  • 25:55 - 25:56
    those adds,
  • 25:56 - 25:57
    that it was a -
  • 25:57 - 25:59
    it didn't change the overall constant running time.
  • 25:59 - 26:02
    So you have to - you kind of think of it maybe in the picture. It does mean every now and
  • 26:02 - 26:05
    then though one of them is gonna surprise you with how slow it is, but
  • 26:05 - 26:06
  • 26:06 - 26:07
    hopefully that's
  • 26:07 - 26:12
    few and far between, if we've chosen our allocation strategy well.
  • 26:12 - 26:15
    So I'm gonna say - actually, I'm gonna do this. I'm gonna call this
  • 26:15 - 26:17
    thing actually double capacity.
  • 26:17 - 26:21
    So one strategy that often is used is you could go in little chunks. You could go like
  • 26:21 - 26:23
    ten at a time all the time.
  • 26:23 - 26:24
    But
  • 26:24 - 26:27
    if the array's gonna get very big,
  • 26:27 - 26:30
    going by tens will take you a lot of time. You might sort of use sometimes the indication of, ''Well
  • 26:30 - 26:33
    how big is it already?'' Then if that's about the size it seems to be, why don't we go ahead
  • 26:33 - 26:34
    and just double.
  • 26:34 - 26:36
    So if we start at 10,
  • 26:36 - 26:39
    you know, and then we go to 20, then we go to 40, then we to 80, then
  • 26:39 - 26:42
    as we get to bigger and bigger sizes, we'll make the kind of assumption that: well,
  • 26:42 - 26:45
    given how big it is already, it's not - it wouldn't surprise us if it got a lot bigger. So
  • 26:45 - 26:48
    let's just go ahead and allocate
  • 26:48 - 26:50
    twice what we have as a way of kind of
  • 26:50 - 26:54
    predicting that it's pretty big now, it might get even bigger in the future. That
  • 26:54 - 26:55
    isn't necessarily
  • 26:55 - 26:58
    the only strategy we could use, but it's one that actually often makes
  • 26:58 - 27:01
    pretty decent sense. And then at any given point, you'll know that the vector will
  • 27:01 - 27:03
    be somewhere between
  • 27:03 - 27:05
    full and half capacity,
  • 27:05 - 27:07
    is what you're setting up for.
  • 27:07 - 27:10
    So let's do this.
  • 27:10 - 27:12
    Oops, it's not ints;
  • 27:12 - 27:14
    string bigger equals,
  • 27:14 - 27:18
    and I make a new string array that is num allocated times two,
  • 27:18 - 27:22
    so twice as big as the one we have.
  • 27:22 - 27:30
    And now I go through and I copy. I'm
  • 27:30 - 27:34
    copying from my old array to my bigger one,
  • 27:34 - 27:37
    all of num used. In this case, num used and num allocated are exactly the same thing, so. And
  • 27:37 - 27:38
    then I'm
  • 27:38 - 27:43
    gonna reset my fields as needed. I'm gonna delete my old array because I'm
  • 27:43 - 27:45
    now done with it. I'm gonna
  • 27:45 - 27:49
    set my pointer to this, so that's doing pointer assignment only. Right? So I deleted
  • 27:49 - 27:52
    the old space, I've copied everything I needed out of it, I'm
  • 27:52 - 27:54
    now resetting my pointer to the bigger one,
  • 27:54 - 27:56
    and then I'm setting my num allocated
  • 27:56 - 28:00
    to be
  • 28:00 - 28:01
    twice as big,
  • 28:01 - 28:05
    num used doesn't change. Okay,
  • 28:05 - 28:06
    so
  • 28:06 - 28:09
    went through the process of building all these things. And as noted, that is gonna
  • 28:09 - 28:11
    cost us something
  • 28:11 - 28:15
    linear in the number of elements that we currently have, so.
  • 28:15 - 28:19
    So this guy is intended to be a private method.
  • 28:19 - 28:22
    I don't want people outside of the vector being able to call this, so I'm actually
  • 28:22 - 28:24
    gonna list this
  • 28:24 - 28:27
    in the private section. It's not as
  • 28:27 - 28:29
    common that you'll see member functions listed down here. But in this case, it's
  • 28:29 - 28:32
    appropriate for something that you plan to use internally as a helper but you don't want
  • 28:32 - 28:39
    anybody outside just to be calling double capacity when they feel like it.
  • 28:39 - 28:41
    Question? So normally [inaudible] an array, you couldn't actually
  • 28:41 - 28:45
    declare a size like that, though, right, with a variable?
  • 28:45 - 28:48
    You know I don't understand the question. Try that again. You
  • 28:48 - 28:52
    know in this case to enlarge it, you use a
  • 28:52 - 28:53
    variable as the - for the
  • 28:53 - 28:57
    size of the array. When you normally declare an array, you couldn't do that, right? Well if
  • 28:57 - 29:03
    you did it - It has to be a constant. So like if you used this form of an array, you know,
  • 29:03 - 29:05
    where you declared it like this. Did you see what I just did?
  • 29:05 - 29:05
    Yeah. Yeah.
  • 29:05 - 29:06
    That way won't work,
  • 29:06 - 29:10
    right? That way is fixed size, nothing you can do about it. So I'm usually totally the
  • 29:10 - 29:14
    dynamic array at all times, so that everything - So you do it when you're declaring it on a heap?
  • 29:14 - 29:15
    Yes. Okay.
  • 29:15 - 29:19
    Yes, exactly. All I have in the - stored in the vector itself is a pointer to an
  • 29:19 - 29:22
    array elsewhere. And that array in the heap gives me the flexibility to make it as big as
  • 29:22 - 29:26
    I want, as small as I want, to change its size, to change where it
  • 29:26 - 29:29
    points to, you know all the - the dynamic arrays typically just give you a lot more flexibility
  • 29:29 - 29:32
    than a static array. That's really stack heap. It is. Array is a
  • 29:32 - 29:35
    stack heap thing. When you put on the stack, you had to say how big it is at compile time
  • 29:35 - 29:38
    and you can't change it. The heap let's you say, ''I need it bigger, I need it smaller, I need to
  • 29:38 - 29:40
    move it,''
  • 29:40 - 29:44
    in a way that the stack just doesn't give you that at all.
  • 29:44 - 29:47
    So when I go back to myvector.cpp, the place I want to put in my
  • 29:47 - 29:54
    double capacity here is when num used is equal to num allocated,
  • 29:54 - 29:58
    but what I want to do is call double capacity there.
  • 29:58 - 30:02
    After I've done that, num allocated should've gone up by a factor of two.
  • 30:02 - 30:04
    Space will be there at that point. I know that num used is a
  • 30:04 - 30:08
    fine slot to now use to assign that next thing. So whenever we're out of space, we'll
  • 30:08 - 30:10
    make some more space.
  • 30:10 - 30:13
    And so I'm gonna - right now, I think my allocated is still set at two. That's a fine place.
  • 30:13 - 30:16
    I'd like it to be kind of small because I'd like to test kind of
  • 30:16 - 30:18
    the -
  • 30:18 - 30:25
    some of the initial allocations. So I'll go ahead and add a
  • 30:25 - 30:28
    couple more people so I can see that I know that - at that point, if I've gotten to
  • 30:28 - 30:32
    five, I'm gonna have to double once and then again to get there.
  • 30:32 - 30:37
    And let's, I'll take out my error case here, see that I've managed
  • 30:37 - 30:38
    to
  • 30:38 - 30:40
    allocate and move stuff around.
  • 30:40 - 30:42
    Got my five names back out
  • 30:42 - 30:46
    without running into anything crazy, so that makes me feel good about what I got
  • 30:46 - 30:49
    there. So
  • 30:49 - 30:53
    I could go on to show you what insert and remove
  • 30:53 - 30:53
    do; I think
  • 30:53 - 30:57
    I'm probably gonna skip that because I'd rather talk about the template thing. But I could
  • 30:57 - 31:01
    just tell you - I could sketch the [inaudible]: what does insert at do, what does remove at do?
  • 31:01 - 31:04
    Basically, that they're doing the string - the array shuffling for you. If you say
  • 31:04 - 31:08
    insert at some position, it has to move everything down by one and then
  • 31:08 - 31:11
    put in there. Whereas at is actually just tacking it onto the end of the existing
  • 31:11 - 31:12
    ones.
  • 31:12 - 31:16
    The insert and remove have to do the shuffle to either close up the space or open up a space.
  • 31:16 - 31:21
    They'll probably both need to look at the capacity as well. That the - if you're
  • 31:21 - 31:25
    inserting and you're already at capacity, you better double before you start. And then the
  • 31:25 - 31:28
    remove at, also may actually want to have a shrink capacity. Where when we realize
  • 31:28 - 31:31
    we previously were allocated much larger and we've gotten a lot smaller, should we
  • 31:31 - 31:35
    take away some of that space. A lot of times the implementations don't bother
  • 31:35 - 31:38
    with that case. They figure, ''Ah, it's already allocated, just keep it around. You
  • 31:38 - 31:41
    might need it again later.'' So it may be that actually we just leave it over-allocated,
  • 31:41 - 31:44
    even when we've deleted a lot of elements, but
  • 31:44 - 31:47
    if we were being tidy we could take an effort there.
  • 31:47 - 31:50
    What I want to do is switch it to a template. So if you have questions
  • 31:50 - 31:53
    about the code I have right here, now would be
  • 31:53 - 31:55
    a really good time to ask before I start
  • 31:55 - 31:57
    mucking it up. Way in the back? [Inaudible].
  • 31:57 - 32:00
    I will. You know that's a really good idea because if I - at this point, I'll
  • 32:00 - 32:03
    start to change it and then it's gonna
  • 32:03 - 32:06
    be something else before we're all done. So let me
  • 32:06 - 32:09
    take a snapshot of what we have here
  • 32:09 - 32:12
    so that I - before I destroy it.
  • 32:12 - 32:14
    Question? When does the deconstructor
  • 32:14 - 32:16
    get
  • 32:16 - 32:19
    called? Okay, so the destructor gets called
  • 32:19 - 32:23
    in the most - there are two cases it gets called. One is when the
  • 32:23 - 32:25
    - so the constructor gets called when you declare
  • 32:25 - 32:29
    it, and then destructor gets called when it goes out of scope. So at the opening brace
  • 32:29 - 32:32
    of the block where you declared it in, is when the constructor's happening,
  • 32:32 - 32:35
    and then when you leave that. So in the case of this program, it's at the end of
  • 32:35 - 32:36
    May,
  • 32:36 - 32:38
    but and if it were in some called function or in the body of a for loop or
  • 32:38 - 32:42
    something, it would get called when you enter the loop and then called as -
  • 32:42 - 32:43
    destroyed as it left.
  • 32:43 - 32:47
    For things that were allocated out of the heap, so if I had a myvector new myvector, it
  • 32:47 - 32:50
    would explicitly when I called delete that thing when I was done with it.
  • 32:50 - 32:55
    So especially when the variable that holds it is going away,
  • 32:55 - 32:58
    right? Either because you're deleting it out of the heap or because it's going out of scope on the
  • 32:58 - 33:00
    stack. Here?
  • 33:00 - 33:04
    When you have string star array, arr, it's
  • 33:04 - 33:07
    a pointer to a single string and then later you can use a new statement
  • 33:07 - 33:08
    to
  • 33:08 - 33:09
    link it to - Yeah. -
  • 33:09 - 33:13
    an array. So how does it know when it - How does it know? It doesn't, is the truth, is that
  • 33:13 - 33:16
    when you say something's a pointer to a string,
  • 33:16 - 33:20
    the only guarantee is really there and says it's an address of someplace where a
  • 33:20 - 33:23
    string lives in memory. Whether there's one string there or a whole sequence of strings
  • 33:23 - 33:27
    is something you decide and you maintain, and so the compiler doesn't distinguish
  • 33:27 - 33:28
    those two cases.
  • 33:28 - 33:30
    It does not know that you made
  • 33:30 - 33:32
    exactly 1 string at the other end of this or 500.
  • 33:32 - 33:36
    And so, that's why this idea of tracking the num used and num allocated becomes our
  • 33:36 - 33:39
    job; that they look exactly the same in terms of how it interprets them. It says, ''Well it's the
  • 33:39 - 33:43
    address of where a string lives in memory, or maybe it's a sequence. I don't know.'' And
  • 33:43 - 33:47
    so it lets you use the brackets and the new and stuff on a pointer without
  • 33:47 - 33:51
    distinguishing - having any mechanism in the language to say this is a single
  • 33:51 - 33:53
    pointer and this is an array pointer. They look the same. So
  • 33:53 - 33:55
    you could use the bracket notion on a single pointer?
  • 33:55 - 34:00
    You certainly can. And then - It's not a good idea but you can do it. So
  • 34:00 - 34:03
    legally in the language, it just makes no distinction between those.
  • 34:03 - 34:06
    They are really commingled in way that - and so that's one of the more surprising features of C
  • 34:06 - 34:08
    and C++ and one's that a little bit hard to get your head around is
  • 34:08 - 34:12
    it doesn't track that it's a pointer to a single thing versus a pointer to an array.
  • 34:12 - 34:14
    That they're both just
  • 34:14 - 34:15
    pointers and it's mine.
  • 34:15 - 34:18
    And that allows opportunity for errors, when you mistreat them as the other type
  • 34:18 - 34:21
    for example. Question? Can you go
  • 34:21 - 34:25
    over in your secret view file in the [inaudible]
  • 34:25 - 34:27
    of what's going on
  • 34:27 - 34:32
    with [inaudible] real quick because it's just - Yeah, yeah, yeah, so let me - it was basically the thing I drew over here, but I'll do it again just to watch
  • 34:32 - 34:33
    it,
  • 34:33 - 34:35
    is that let's start - let's imagine I have a slightly smaller
  • 34:35 - 34:37
    num allocated so it's a little
  • 34:37 - 34:38
    less
  • 34:38 - 34:42
    for me to write. So let's say that I'm gonna use a num allocated of two, so this allocates
  • 34:42 - 34:43
    two. So
  • 34:43 - 34:45
    when I construct it, it makes a
  • 34:45 - 34:48
    block that holds two things and num used is
  • 34:48 - 34:51
    zero. So I do two adds: I add A, it
  • 34:51 - 34:53
    increments num used to one;
  • 34:53 - 34:55
    I had B, it increments num used to two.
  • 34:55 - 34:57
    I try to add C.
  • 34:57 - 34:59
    It says, ''Oh, well num used equals num allocated.
  • 34:59 - 35:01
    We're gonna go to double capacity now.''
  • 35:01 - 35:07
    So double capacity has this little local variable called bigger.
  • 35:07 - 35:08
    And it says bigger
  • 35:08 - 35:10
    is gonna be something that is
  • 35:10 - 35:13
    four strings worth in an array, so it
  • 35:13 - 35:14
    gets four out there.
  • 35:14 - 35:15
    It does a full loop
  • 35:15 - 35:19
    to copy the contents of the old array on top of the initial part of this array; so it
  • 35:19 - 35:22
    copies over the A and the B,
  • 35:22 - 35:23
    into there.
  • 35:23 - 35:27
    And then it goes, ''Okay, I'm done with this old part. So let me go ahead
  • 35:27 - 35:30
    and delete that.'' And then it resets the arr to
  • 35:30 - 35:34
    point to this new one down here, where bigger was. So now, we got to aliases of the
  • 35:34 - 35:35
    same location.
  • 35:35 - 35:38
    And then it sets my num allocated to say and now
  • 35:38 - 35:39
    what you've got there
  • 35:39 - 35:41
    is something that holds four slots.
  • 35:41 - 35:45
    And then that used call here says, ''Okay and now writer the C into
  • 35:45 - 35:48
    the slot at three.''
  • 35:48 - 35:51
    So the process here is the only way to enlarge an array in C++ is to make
  • 35:51 - 35:54
    a bigger one, copy what you had,
  • 35:54 - 35:57
    and then by virtue of you having made a bigger array to start with, you have some more slack that
  • 35:57 - 35:59
    you didn't have before.
  • 35:59 - 36:02
    Daniel? How does it delete arr with a star?
  • 36:02 - 36:05
    You know it has to do with just delete takes a pointer.
  • 36:05 - 36:09
    It does it - so a star arr is a string, arr is a pointer to a string. So
  • 36:09 - 36:13
    both forms of delete, delete and delete bracket - So conceptually - - a pointer. - there is a start
  • 36:13 - 36:16
    there because it's delete - Well effectively, yeah. It's delete the thing at the other end of the pointer, really.
  • 36:16 - 36:19
    But it's funny. Delete says
  • 36:19 - 36:21
    take this address and reclaim its contents.
  • 36:21 - 36:25
    And so it doesn't really operate on a string, per se, it operates on the storage
  • 36:25 - 36:29
    where that string is. And so I don't know whether you want to call that is there an implicit star there or
  • 36:29 - 36:33
    not, it really is about the pointer though rather than the contents.
  • 36:33 - 36:38
    So saying that address has some memory associated with it, reclaim that memory. If I could raise -
  • 36:38 - 36:39
    Uh-huh.
  • 36:39 - 36:41
    So when you're
  • 36:41 - 36:45
    first declaring or when you're making a pointer like string bigger, string star bigger,
  • 36:45 - 36:47
    you have to declare it with
  • 36:47 - 36:50
    the star notion. But then later on, you don't ever have to use
  • 36:50 - 36:53
    that again? You pretty much won't see that star used again.
  • 36:53 - 36:56
    Right? It's interesting that things like bigger sub I and erase sub I
  • 36:56 - 37:00
    implicitly have a D reference in them. And that can be misleading. You
  • 37:00 - 37:02
    think, ''Well how come I'm never actually using that star again on that thing to
  • 37:02 - 37:04
    get back to the strings that are out there?''
  • 37:04 - 37:08
    And it has to do with the fact that the bracket notation kind of implicitly D
  • 37:08 - 37:09
    references in it.
  • 37:09 - 37:13
    If I did a star bigger, it would actually have the effect of giving me bigger
  • 37:13 - 37:16
    sub zero, it turns out. You can use that notation but it's
  • 37:16 - 37:18
    not that common to need to. And
  • 37:18 - 37:19
    so down on
  • 37:19 - 37:20
    the last,
  • 37:20 - 37:23
    one line up
  • 37:23 - 37:24
    from the bottom, it says array equals bigger. You don't have to - Yeah,
  • 37:24 - 37:27
    if you did that, if I did say - If you
  • 37:27 - 37:33
    said array - Star arr equals star bigger,
  • 37:33 - 37:35
    I would not be getting what I want.
  • 37:35 - 37:37
    Right? What it would be doing is it would say
  • 37:37 - 37:40
    follow bigger and see what's at the other end, so that would follow bigger and
  • 37:40 - 37:44
    get that string A. And then it would say follow ARR and overwrite it
  • 37:44 - 37:45
    with that A,
  • 37:45 - 37:49
    so it would actually have the effect of only copying the first string
  • 37:49 - 37:51
    from bigger on top of the first string of array. But array would still point to
  • 37:51 - 37:54
    where it was, bigger would still point to where it was, and they would - we
  • 37:54 - 37:56
    would've not have updated our,
  • 37:56 - 38:00
    the pointer we really wanted to point to the new array. So
  • 38:00 - 38:02
    there is a difference. Without the star,
  • 38:02 - 38:05
    we're talking about the changing the pointers; with the star, we're
  • 38:05 - 38:08
    talking about the strings at the other end. And so we're - this is a string
  • 38:08 - 38:10
    assignment. It says assign one string to another.
  • 38:10 - 38:12
    Without
  • 38:12 - 38:15
    the star on it, it's like assign one pointer to another;
  • 38:15 - 38:18
    make two pointers point to the same place. When you're done with this,
  • 38:18 - 38:23
    bigger and arr will be aliases for the same location.
  • 38:23 - 38:25
    That's a very important question though to get kind of
  • 38:25 - 38:30
    what that star's doing for you. Here? After
  • 38:30 - 38:34
    arr is bigger, can
  • 38:34 - 38:35
    you delete bigger after that? If I deleted
  • 38:35 - 38:39
    bigger, at that point arr is pointing to the same place. And so remember that
  • 38:39 - 38:42
    having two or three or ten pointers all at the same place, if you delete one of them,
  • 38:42 - 38:46
    they actually effectively are deleted. The delete really deletes the
  • 38:46 - 38:49
    storage out here. And then if I did that, it would cause arr to then be pointing to this
  • 38:49 - 38:51
    piece of memory,
  • 38:51 - 38:54
    and not a good scene will come from that. It means that when it later
  • 38:54 - 38:57
    goes back in there and starts trying to read and write to that contents at
  • 38:57 - 39:00
    any moment it could kind of shift underneath you. You don't own it any
  • 39:00 - 39:02
    more; it's not reserved for your use.
  • 39:02 - 39:05
    So if we did that, we'd get ourselves into trouble. All
  • 39:05 - 39:08
    right? So there should basically be a one-to-one correspondence between
  • 39:08 - 39:10
    things you new and things you
  • 39:10 - 39:11
    delete. And so
  • 39:11 - 39:14
    in the myvector case, we newed something in the constructor that we're gonna delete in the
  • 39:14 - 39:18
    destructor. If at some point along the way we got rid of our old one and get
  • 39:18 - 39:21
    a new one, that's the new the one that's gonna get deleted. If we deleted it
  • 39:21 - 39:23
    midstream here, we would just be asking for
  • 39:23 - 39:29
    havoc when we start accessing that deleted memory. Way in the back? Is
  • 39:29 - 39:31
    it possible to create a pointer
  • 39:31 - 39:33
    to something -
  • 39:33 - 39:37
    a pointer to the address that's one off the end of the original
  • 39:37 - 39:42
    array and then just create an array just off the end there? Not really. So new doesn't let
  • 39:42 - 39:43
    you decide where you want something.
  • 39:43 - 39:45
    So you're point being to think,
  • 39:45 - 39:48
    ''Well I can tell you what this address is, can I just make space right there
  • 39:48 - 39:53
    and then I won't have to copy.'' And it turns out new just doesn't give you that kind of control. You ask it for space, it
  • 39:53 - 39:55
    finds it wherever it has and you can't -
  • 39:55 - 39:58
    there isn't even a mechanism where you could suggest where you'd like it to be. You could say, ''Well
  • 39:58 - 40:01
    let that place right there would be really handy. Could you please give me that one?'' It
  • 40:01 - 40:02
    just doesn't give it you.
  • 40:02 - 40:03
    So
  • 40:03 - 40:05
    you're - this is the way
  • 40:05 - 40:08
    that typically you have to manage a dynamic array. And this is actually one of the big
  • 40:08 - 40:10
    drawbacks
  • 40:10 - 40:13
    to continuous memory as a reason for implementing things is that the
  • 40:13 - 40:16
    fact that it has to maintain contiguousness. Means you have to shuffle and move
  • 40:16 - 40:18
    and copy
  • 40:18 - 40:19
    this block
  • 40:19 - 40:20
  • 40:20 - 40:23
    without the flexibility of something like a link list where every cell is independently
  • 40:23 - 40:27
    manipulated.
  • 40:27 - 40:29
    There? Why does [inaudible] the delete
  • 40:29 - 40:34
    brackets arr as delete just arr? So the difference is that if you allocated
  • 40:34 - 40:38
    something with new string bracket, new something bracket, you need a delete bracket.
  • 40:38 - 40:41
    If you actually use delete without the brackets, it thinks there's a single
  • 40:41 - 40:42
    pointer and there's only one string at the other end.
  • 40:42 - 40:47
    Where delete brackets says delete the whole gob of strings that are there.
  • 40:47 - 40:49
    If you don't do it, it's not - the consequence is not that big;
  • 40:49 - 40:52
    it's like some memory gets orphaned, some things don't happen. But
  • 40:52 - 40:56
    to be totally correct, they go hand in hand: if you use new with
  • 40:56 - 40:59
    brackets, use delete with no brackets, if you use new with brackets, use delete with brackets.
  • 40:59 - 41:02
    So it's either both with brackets or both without.
  • 41:02 - 41:04
    So even though arr is just point
  • 41:04 - 41:07
    to the first place, the
  • 41:07 - 41:08
    brackets knows the -
  • 41:08 - 41:12
    Yeah, it does. And so that kind of makes me feel like I'm a lair because I said well the array
  • 41:12 - 41:15
    doesn't know its length. Well it does somehow. Internally it is
  • 41:15 - 41:18
    maintaining some housekeeping but it doesn't expose it to you.
  • 41:18 - 41:21
    So when you say delete bracket arr it knows, ''Oh, there's a bunch of strings and I got
  • 41:21 - 41:25
    to do a bunch of cleanup on them.'' But it doesn't ever expose that information back
  • 41:25 - 41:29
    to you. It doesn't let you depend on it, so it's up to you to maintain that information redundantly
  • 41:29 - 41:34
    with it. All
  • 41:34 - 41:36
    right, let me see if I can make it a template.
  • 41:36 - 41:39
    I probably can't do this actually fast enough to get it all done today, but we can at least get started
  • 41:39 - 41:41
    on it.
  • 41:41 - 41:42
    So then, I
  • 41:42 - 41:46
    introduce a template header and
  • 41:46 - 41:49
    I make up the name that I want here, so
  • 41:49 - 41:50
    same class header now
  • 41:50 - 41:52
    other than typing elem type. Then
  • 41:52 - 41:55
    I look through my interface and I see places where I previously had said it's
  • 41:55 - 41:59
    strings, it's strings, it's storing strings. And I say it's not actually storing strings;
  • 41:59 - 42:00
    it's gonna store
  • 42:00 - 42:02
    elem type things,
  • 42:02 - 42:06
    it's gonna return elem type things
  • 42:06 - 42:09
    and it's going to have an array of
  • 42:09 - 42:11
    elem type things.
  • 42:11 - 42:13
    So I think that's everything that happened
  • 42:13 - 42:17
    to the interface. Let me see if I see any other places that I - so the
  • 42:17 - 42:18
    interface part
  • 42:18 - 42:20
    is kind of small.
  • 42:20 - 42:23
    There's one other change I'm gonna have to make to it but I'm gonna come back to it. I'm gonna look
  • 42:23 - 42:25
    at the code at the other side for a second. And I say, ''Okay, well
  • 42:25 - 42:28
    that wasn't so bad.'' Now
  • 42:28 - 42:31
    it turns out that it gets a little bit goopier over here
  • 42:31 - 42:33
    because that template type name
  • 42:33 - 42:38
    has to go on every one of these:
  • 42:38 - 42:40
    introduce them to the template type and elem type.
  • 42:40 - 42:44
    And now there's another place where it needs to show up.
  • 42:44 - 42:49
    So the full syntax for this is now saying this is a template function,
  • 42:49 - 42:50
    depending on elem type,
  • 42:50 - 42:52
    and it's actually for the myvector
  • 42:52 - 42:54
    who is being -
  • 42:54 - 42:58
    we are writing the myvector constructor for something whose name is myvector
  • 42:58 - 43:00
    angle bracket elem type.
  • 43:00 - 43:02
    So there's gonna be a lot of this goo. Every one of these is kinda change
  • 43:02 - 43:05
    its form, from just looking like the ordinary myvector class scope doesn't
  • 43:05 - 43:06
    really exist any more.
  • 43:06 - 43:10
    Myvector is now a template for which there's a lot of different class scopes,
  • 43:10 - 43:13
    one for each kind of thing being stored. So myvector int is different than myvector
  • 43:13 - 43:14
    string.
  • 43:14 - 43:15
    So we say, ''Well,
  • 43:15 - 43:18
    if you were building the myvector constructor for myvector string, it
  • 43:18 - 43:21
    looks like this.'' Or you know
  • 43:21 - 43:24
    having filled an elem type with those strings. So
  • 43:24 - 43:30
    everywhere I was using string, I got to change to elem type in the body as well. And
  • 43:30 - 43:32
    then I kind of take this guy
  • 43:32 - 43:38
    and use it in a bunch of places. I'm gonna use it here
  • 43:38 - 43:39
    and then I'm gonna have to do it down
  • 43:39 - 43:50
    here, on that side, do it
  • 43:50 - 43:54
    here, and it's gonna return something of elem type,
  • 43:54 - 43:56
    here. It's a little bit of
  • 43:56 - 43:59
    a mess to do this, and the code definitely gets a little bit goopier as a result
  • 43:59 - 44:00
    of this. It doesn't
  • 44:00 - 44:08
    look quite as pretty as it did when it wasn't a template,
  • 44:08 - 44:11
    but it becomes a lot more useful. Okay.
  • 44:11 - 44:14
    Then I need to look for places that I used a string.
  • 44:14 - 44:17
    And every place where I was using string, assuming that's what I was storing, it
  • 44:17 - 44:20
    now actually turns into elem type. So
  • 44:20 - 44:23
    my pointers and the kind of array I'm allocating is actually now made into elem
  • 44:23 - 44:24
    type.
  • 44:24 - 44:27
    The rest of the code actually didn't say anything specific about what's its doing, just copying
  • 44:27 - 44:30
    things from one array to another. And now, depending on what the arrays are, it's
  • 44:30 - 44:32
    copying ints or strings or doubles.
  • 44:32 - 44:36
    And then other places in the interface where I'm doing add or I'm going get at, I have to be
  • 44:36 - 44:40
    describing the things that are coming in and out as elem type so that they can be
  • 44:40 - 44:42
    matched to whatever the client's using. I
  • 44:42 - 44:45
    think the rest of it looks okay. Why do you have to write
  • 44:45 - 44:47
    template type name, and elem type above
  • 44:47 - 44:50
    every - Because you just have to, because it's C++. Because the thing is,
  • 44:50 - 44:53
    that piece of code is, itself, a template, so
  • 44:53 - 44:56
    these are like little mini-templates. So that I had the interface, which said here's the
  • 44:56 - 44:58
    template pattern for the
  • 44:58 - 45:02
    interface, and each of these says when you're ready to make the size member function for a vector of int,
  • 45:02 - 45:05
    it comes off this template. So this template describes what the size member function
  • 45:05 - 45:09
    looks like for any of the myvectors you might instantiate. And it describes the
  • 45:09 - 45:12
    template because, in fact, we need to build a new size for
  • 45:12 - 45:14
    ints versus doubles versus strings.
  • 45:14 - 45:17
    It's even funny because you think of my size like, ''Well size doesn't even
  • 45:17 - 45:21
    use anything related to the elem type.'' But in fact, each of the member functions
  • 45:21 - 45:25
    is kinda specific. It's not just a myvector size; it's the myvector int size, the
  • 45:25 - 45:26
    myvector string size.
  • 45:26 - 45:30
    And that for some of the member functions it's quite obvious why you need a distinct
  • 45:30 - 45:33
    copy. Get at returns an int in some cases and a double in others;
  • 45:33 - 45:36
    but even though ones that don't appear to have any dependence on the elem type,
  • 45:36 - 45:37
    actually are
  • 45:37 - 45:40
    separated into their own
  • 45:40 - 45:41
    individual versions.
  • 45:41 - 45:45
    So I think I got all of that fixed, and then I'm gonna have to do one thing that's gonna seem
  • 45:45 - 45:49
    really quirky. And it is very quirky but it is C++. Let me show
  • 45:49 - 45:51
    you what I'm gonna do.
  • 45:51 - 45:59
    Is I'm going [inaudible] out of the project. Okay,
  • 45:59 - 46:01
    stop compiling that.
  • 46:01 - 46:01
    And I'm gonna change
  • 46:01 - 46:12
    how it is that myvector gets compiled by doing this. Okay. Take
  • 46:12 - 46:14
    a deep breath.
  • 46:14 - 46:15
    This is really
  • 46:15 - 46:18
    just an oddity of C++.
  • 46:18 - 46:20
    So the situation is this: that
  • 46:20 - 46:23
    templates aren't really compiled ahead of time,
  • 46:23 - 46:25
    templates are just patterns.
  • 46:25 - 46:26
    You know? They like describe
  • 46:26 - 46:30
    a recipe for how you would build a myvector class.
  • 46:30 - 46:34
    But you can't just compile myvector and be done with it because until the client
  • 46:34 - 46:37
    uses it, you don't know what kind of myvectors you're building. Are they myvectors of ints
  • 46:37 - 46:39
    or strings or pseudo structures?
  • 46:39 - 46:43
    So it turns out that the myvector really needs to get compiled
  • 46:43 - 46:46
    at the usage, at the instantiation. When you're ready to make a myvector of
  • 46:46 - 46:50
    students, it then needs to see all the code for myvector so it can go build you a
  • 46:50 - 46:53
    myvector for students on the fly.
  • 46:53 - 46:56
    In order to see that code, it actually has to be present in a different way than
  • 46:56 - 46:59
    most code. Most code is compiled, instead of .cpp, it just
  • 46:59 - 47:02
    gets compiled once and once for all. The random library, random integer doesn't
  • 47:02 - 47:06
    change for anybody usage, there's a random.cpp. It compiled the function.
  • 47:06 - 47:07
    You're done.
  • 47:07 - 47:11
    So the template code does not get compiled ahead of time. It doesn't get listed in the
  • 47:11 - 47:13
    project. What happens is the .h
  • 47:13 - 47:17
    typically has not only the interface, but actually all the code.
  • 47:17 - 47:21
    And so the two ways to get the code in here, one way is I could've just put all the
  • 47:21 - 47:24
    code down here. And that's the way a lot of professional code gets written, it has
  • 47:24 - 47:28
    the interface followed by all the template code right after it. I
  • 47:28 - 47:32
    like to keep us thinking about the interface and the implementation being
  • 47:32 - 47:32
    separate,
  • 47:32 - 47:35
    so I'm actually taking the interface and keeping the .h, keeping this [inaudible]
  • 47:35 - 47:36
    over here
  • 47:36 - 47:42
    in a .cpp. And then I'm using the #include mechanism in a very unusual way. That almost
  • 47:42 - 47:45
    never would you want to, in a regular usage, to #include another
  • 47:45 - 47:49
    .cpp file. For templates, we're making an exception. And we're saying, ''Well
  • 47:49 - 47:53
    in this case, because I really need that code there,'' the #include mechanism is
  • 47:53 - 47:57
    basically saying go take the contents of this thing and just dump it in here.
  • 47:57 - 48:01
    It really is an include mechanism. It says, ''Go get this file and take its text
  • 48:01 - 48:03
    contents and dump it right into this file.''
  • 48:03 - 48:06
    So that when somebody's trying to import the myvector.h,
  • 48:06 - 48:09
    they're getting both the interface plus all the code that we'll generate a
  • 48:09 - 48:11
    pattern from.
  • 48:11 - 48:13
    So this is definitely just a quirk.
  • 48:13 - 48:14
    There's no
  • 48:14 - 48:16
  • 48:16 - 48:18
    consistency between how other languages that do stuff like this expect
  • 48:18 - 48:19
    this.
  • 48:19 - 48:22
    This is just unique to C++ and its compilation mechanisms that require
  • 48:22 - 48:24
    this kind of sort of slight
  • 48:24 - 48:26
    variation in handling.
  • 48:26 - 48:29
    So we'll see this for all the templates we'll use is that
  • 48:29 - 48:33
    they will not be included as normal cpp files, they will get included in the .h.
  • 48:33 - 48:35
    And there is this exact pattern, which is
  • 48:35 - 48:39
    reproduced for every one of the ones in the text. You'll see it on stack and queue and
  • 48:39 - 48:44
    integer. That it becomes the kind of boilerplate we'll use when making a template. So
  • 48:44 - 48:45
    in general, I'd say
  • 48:45 - 48:49
    be very wary of anything that looks like this. This is not a normal thing to do
  • 48:49 - 48:52
    and we're doing it just specifically to kind of keep up the illusion that the
  • 48:52 - 48:55
    interface and the implementation are kept separate because there's actually
  • 48:55 - 48:57
    some good thinking that comes from that.
  • 48:57 - 49:00
    But the way the compiler sees it, it doesn't want them to be separate, and so
  • 49:00 - 49:06
    we have to accommodate it with this little hack, let's say, here.
  • 49:06 - 49:08
    So once I've done that,
  • 49:08 - 49:10
    I go back to lecture.
  • 49:10 - 49:14
    If I change this to be myvector string,
  • 49:14 - 49:16
    I'm hoping
  • 49:16 - 49:19
    that everything will still work.
  • 49:19 - 49:20
    Which it did, kind
  • 49:20 - 49:21
    of amazingly. Daniel?
  • 49:21 - 49:23
    So
  • 49:23 - 49:27
    where is the myvector.cpp file at? So it's actually just living in the same directory with this,
  • 49:27 - 49:30
    the way myvector.h is. So typically, like your .h files are just sitting in the directory - .cpp is sitting in the
  • 49:30 - 49:34
    same directory. That's where it's gonna look for it when it
  • 49:34 - 49:38
    goes #including is in the kind of local contents. But like
  • 49:38 - 49:39
    where is that? Like is it in
  • 49:39 - 49:42
    resources? No, it's just - if you look - you know this is the directory I have, this
  • 49:42 - 49:43
    is the
  • 49:43 - 49:47
    contents of my, you know all my files, my project files, where the thing gets dumped. Oh, okay. It's just sitting there with all
  • 49:47 - 49:50
    the code.
  • 49:50 - 49:53
    And I should be able to
  • 49:53 - 49:57
    change this now to put some numbers in
  • 49:57 - 50:03
    and have it do both. I just did it
  • 50:03 - 50:05
    with strings and now I'm gonna do it with ints.
  • 50:05 - 50:06
    And
  • 50:06 - 50:10
    voila, we now have something that holds ints. So a certain
  • 50:10 - 50:12
    amount of goo that went from
  • 50:12 - 50:14
    the simple form to the template form,
  • 50:14 - 50:18
    but a lot of power gained. Suddenly we took this thing that was one purpose,
  • 50:18 - 50:21
    that held strings only, and you just made it to where it can hold anything you
  • 50:21 - 50:23
    can think of to stick in there
  • 50:23 - 50:24
  • 50:24 - 50:26
    by making
  • 50:26 - 50:28
    little machinations in the
  • 50:28 - 50:29
    syntax there.
  • 50:29 - 50:34
    So we'll see a lot more of this. It's not the first, nor the last, syntax that - for templates that we're gonna be playing
  • 50:34 - 50:36
    with, but that will be next week. Come to Cafe with me, if you
  • 50:36 - 50:45
    got some time. Otherwise, I will see you on Monday.
Title:
Lecture 18 | Programming Abstractions (Stanford)
Description:

Lecture 18 by Julie Zelenski for the Programming Abstractions Course (CS106B) in the Stanford Computer Science Department.

Julie introduces the 'implement vector' and discusses ADTs (abstract data types) in more detail. She then develops a Vector from the ground up, explaining each step as she goes.

Complete Playlist for the Course:
http://www.youtube.com/view_play_list?p=FE6E58F856038C69

CS 106B Course Website:
http://cs106b.stanford.edu

Stanford Center for Professional Development:
http://scpd.stanford.edu/

Stanford University:
http://www.stanford.edu/

Stanford University Channel on YouTube:
http://www.youtube.com/stanforduniversity/

more » « less
Video Language:
English
Duration:
50:54
N. Ueda edited English subtitles for Lecture 18 | Programming Abstractions (Stanford)
Eunjeong_Kim added a translation

English subtitles

Revisions