CS 70

Mysterious Mysteries (Optional)

This page is optional (although you do still need to visit it, which you clearly have!). It's here for those who are curious about the differences between C++ and Java, and in particular, how C++ allows you to do things that Java doesn't let you do, and why you see new so much more in Java code than in C++. If you're not curious, you can skip this page and move on to the next one.

Mysterious Mysteries Demystified: Familiar Syntax

  • Watson speaking

    Sherlock, if we were going to allocate an object on the heap, what would that look like?

  • Sherlock speaking

    Why, my dear Dr. Watson, it would look like this:

    Cow* buttercup = new Cow{5, 3};
    
  • Dog speaking

    Gasp! That looks like Java!

  • Jo speaking

    Sure does!! I'd say

    Cow buttercup = new Cow(5, 3);
    
  • Sherlock speaking

    It really does. Do you know why?

  • Dog speaking

    No! Tell me! Telll mmeeeeeee!

  • Jo speaking

    I know!! Because in Java, every object is allocated on the heap and every variable that refers to an object is a pointer variable!!!

  • Dog speaking

    Whoa…

  • Sherlock speaking

    What do you get in Java if you try to use a variable that you haven't assigned anything to?

  • Dog speaking

    A NullPointerException? Oh. My. Dog.

  • Jo speaking

    I'm so embarrased about that exception name. We'd been so good about pretending there weren't any pointers by just calling them “references” everywhere instead to help everyone be chill with so many pointers, uh, indirections, and then we had to go and name an exception after a pointer. We forgot just one time and it's been haunting us ever since. I blame a late night and too much… uh… cake, yeah, that's it.

  • Sherlock speaking

    As we've discussed, a null pointer is a pointer with the value nullptr, which is not a valid address. A null pointer essentially means “not a valid pointer”.

  • Watson speaking

    Java default-initializes all pointers to be null precisely so it can know to raise this exception if you haven't assigned a valid address.

  • Sherlock speaking

    Whereas C++ default-initializes pointers like they were primitive numeric types: with whatever is already at that spot in memory. As usual, that behavior means less overhead but more danger.

Mysterious Mysteries Demystified: toString

  • Sherlock speaking

    Have you ever called toString on an object in Java where you didn't specifically define a toString function?

  • Dog speaking

    Sure, it just gives you some gobbledygook.

  • Sherlock speaking

    Oh, but it's not gobbledygook. You get something like Cow@458ad742, right?

  • Dog speaking

    Yeah, exactly. The part before the @ is the class name, but after that it's just some garbage.

  • Sherlock speaking

    No, it's a number!

  • Dog speaking

    That can't be a number! It has letters in it!!

  • Sherlock speaking

    It's a number in hexadecimal (base-16) notation. Instead of the digits 0, 1, 2, 3, 4, 5, 6, 8, and 9 (for base-10) hex numbers use the “hexits” 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, and f.

  • Watson speaking

    So that number (0x458ad742) is actually (2 × 1) + (4 × 16) + (7 × 162) + (13 × 163) + (10 × 164) + (8 × 165) + (5 × 166) + (4 × 167).

  • Sherlock speaking

    So that's a really big non-negative number—

  • Watson speaking

    It's 1,166,726,978!

  • Sherlock speaking

    —do you know what that number represents?

  • Dog speaking

    No, no. It can't be!

  • Sherlock speaking

    It's the memory address of that object on the heap!

  • Dog speaking

    I'm dead. I'm literally dead. This killed me.

  • Jo speaking

    Maybe a jolt of caffeine will help bring you back to life? And like, pointers are cool, even if I'm a bit ashamed of them and try to hide them sometimes.

Mysterious Mysteries Demystified: Unfamiliar Syntax

  • Sherlock speaking

    So the reason for some of the unfamiliar syntax in C++ is that C++ allows you do something that Java doesn't!

  • Jo speaking

    In Java, every object is on the heap!! And you always interact with objects through a pointer!!!

  • Sherlock speaking

    But in C++ you can put objects in the stack! You can put objects directly inside other objects (rather than pointers to objects)! You can directly access an object or you can indirectly access it through a pointer.

  • Watson speaking

    Which can explain a lot!

  • Sherlock speaking

    Why is there no Java equivalent to Cow mabel{3, 2};?

  • Watson speaking

    Because that C++ code declares an object on the stack and Java doesn't let you do that!

  • Sherlock speaking

    Why does C++ have both the dot operator and the arrow operator to access members?

  • Watson speaking

    Because one is for objects and one is for pointers to objects.

  • Jo speaking

    Java only has pointers to objects, so Java only needs one member-access operator (we chose the dot operator).

  • Dog speaking

    This is incredible! (I'm okay!)

  • Jo speaking

    But all that choice makes C++ more complicated. In Java, we like to have some mental space to think about things like factory factories and abstract factories and factories that make factories that make factories, and so on. But in C++, you can just put a Cow in a Barn and be done with it!

Mysterious Mysteries Demystified: Initialization List

  • Hedgehog speaking

    Talking about being needlessly complicated, what's up with initializer lists?

  • Sherlock speaking

    Well, when an object is created we need to initialize all of its member variables before the constructor starts.

  • Watson speaking

    Remember from the data lifecycle lesson: We can't use a variable until it has been initialized!

  • Sherlock speaking

    Java doesn't need initializer lists because every variable that refers to an object is a pointer. All the pointer members in Java can be default-initialized to null pointers, and then reassigned later.

  • Watson speaking

    In C++ it's possible for an object to “contain” an object; like a Barn containing a Cow (rather than containing a pointer to a Cow).

  • Sherlock speaking

    So when we allocate and initialize a Barn, we must also allocate and initialize the Cow in the Barn.

  • Watson speaking

    All of that happens before we start running the code (inside the braces) in Barn's constructor! Otherwise, we'd start the body with some garbage memory where the Cow object is supposed to be and we couldn't expect any of the Cow methods (including assignment!) to work properly in that scenario.

  • Sherlock speaking

    Since Cow has no default constructor, we can't default initialize it. There's no such thing as a “null Cow”.

  • Watson speaking

    We need to give parameters to the Cow constructor before we enter the constructor for Barn.

  • Sherlock speaking

    That's what the initializer list is for!

  • Dog speaking

    I kind of, sort of get it. I think.

  • Sherlock speaking

    Yeah, it's a lot. The point is that C++ needs initializer lists because it allows direct access to objects, whereas Java only allows access through pointers.

  • Watson speaking

    You can really see the design philosophies of these languages in play here. C++ focuses on programmer choice and minimal overhead: put objects wherever you want them and only use pointers when you need to.

  • Sherlock speaking

    When Java came along, it limited how you could allocate and interact with objects, trading some of that freedom for the sake of simplicity and safety.

  • Watson speaking

    Both philosophies are important and valid! There are lots of programming languages because there are lots of different problems and lots of different programmers!

  • Rabbit speaking

    In reality, whenever language designers try to make a language “simpler” to be easier to use, programmers themselves just make it all more complicated again by building more and more complex libraries or coding idioms on top of it. So real-world coding in just about any language is going to get complicated somewhere along the way. Each language ends up with its own internal culture that is a reflection of the language's design philosophy and the kinds of problems it's used to solve, but may be tricky to learn for newcomers.

(When logged in, completion status appears here.)