Live data from Hacker News

Bjarne Stroustrup – The Essence of C++ [video]

channel9.msdn.com

61–70 of 85 posts

Re: Bjarne Stroustrup – The Essence of C++ [video]

#61
post #26

If you've ever wondered what's the deal with C++ and why it's being used in 2013, you might wanna watch this. Stroustrup isn't a very flashy speaker, but he says some incredibly insightful things. C++'s C heritage makes it hard to master and also causes countless misconceptions. Even if you never want to use C++, it's worth looking into some of the unique concepts that, sadly, didn't catch on in other languages so fa…

There are also some things that are powerful but I'm not quite sure if I really like them. For instance, he promotes the use of handles instead of pointers. He goes through these variants: Gadget* p = new Gadget(n); // not exception safe shared_ptr p{new Gadget(n)}; //exception safe unique_ptr p{new Gadget(n)}; //exception safe and less wasteful than shared_ptr if local Gadget g{n}; //his preferred solution My proble…

Somehow I don't find this to be a problem in my code. Yes, when using someone else's library you need to know how they handle ownership. But this is basically a problem inherited from C.

For example, in the code you posted all the pointer-like handles are named 'p'. In my experience, if we consistently pursue minimal scope and minimal lifetime for our objects, then longer-lived objects are oddballs and we use the type of the handle to help describe its ownership strategy.

Re: Bjarne Stroustrup – The Essence of C++ [video]

#62
post #56

Earlier quoted context omitted.

There are also some things that are powerful but I'm not quite sure if I really like them. For instance, he promotes the use of handles instead of pointers. He goes through these variants: Gadget* p = new Gadget(n); // not exception safe shared_ptr p{new Gadget(n)}; //exception safe unique_ptr p{new Gadget(n)}; //exception safe and less wasteful than shared_ptr if local Gadget g{n}; //his preferred solution My proble…

> My problem with his preferred solution is that I cannot know that Gadget is really a handle to a shared Gadget and not a big fat Gadget value on the stack. The only way of knowing that is to look at the implementation or the documentation. I'd say you do not _need_ to know. If Gadget contains tons of data, it's wiser for it to just put that on the heap, internally. Like std::vector does. As long as Gadget handles (…

I disagree. You have to be absolutely certain at all times whether you're holding on to a reference to a shared data structure or you have your own copy, unless the object is immutable. This is not just a performance thing.

Re: Bjarne Stroustrup – The Essence of C++ [video]

#63

Earlier quoted context omitted.

There are also some things that are powerful but I'm not quite sure if I really like them. For instance, he promotes the use of handles instead of pointers. He goes through these variants: Gadget* p = new Gadget(n); // not exception safe shared_ptr p{new Gadget(n)}; //exception safe unique_ptr p{new Gadget(n)}; //exception safe and less wasteful than shared_ptr if local Gadget g{n}; //his preferred solution My proble…

Somehow I don't find this to be a problem in my code. Yes, when using someone else's library you need to know how they handle ownership. But this is basically a problem inherited from C. For example, in the code you posted all the pointer-like handles are named 'p'. In my experience, if we consistently pursue minimal scope and minimal lifetime for our objects, then longer-lived objects are oddballs and we use the typ…

I agree that this is an issue with third party libraries, not with my own code. But C++ libraries can be a real horror. Every single one of them comes with its own peculiar memory management idea. Recently I started to use rapidjson. It's insanely fast but that's not the only insanity. It basically screams for memory management bugs.

Re: Bjarne Stroustrup – The Essence of C++ [video]

#64

Earlier quoted context omitted.

There are also some things that are powerful but I'm not quite sure if I really like them. For instance, he promotes the use of handles instead of pointers. He goes through these variants: Gadget* p = new Gadget(n); // not exception safe shared_ptr p{new Gadget(n)}; //exception safe unique_ptr p{new Gadget(n)}; //exception safe and less wasteful than shared_ptr if local Gadget g{n}; //his preferred solution My proble…

Somehow I don't find this to be a problem in my code. Yes, when using someone else's library you need to know how they handle ownership. But this is basically a problem inherited from C. For example, in the code you posted all the pointer-like handles are named 'p'. In my experience, if we consistently pursue minimal scope and minimal lifetime for our objects, then longer-lived objects are oddballs and we use the typ…

Ever done any enterprise C development?

This is a very big problem in enterprise size code basis, specially with the rotation of external developers.

Re: Bjarne Stroustrup – The Essence of C++ [video]

#65

Earlier quoted context omitted.

Java 7 introduced a new language construct, called the try-with-resources statement, for automatic resource management: void foo() { try (open file or resource here) { // do stuff } // after try block, resource will close automatically } This works with non-memory resources such as files, streams, sockets, and database connections.

Pasting a response: Blocks are an improvement, but not the same as RAII. A block is literally converted to a try-finally by the compiler. It is the same thing with a cleaner syntax. There is no safety added to the old Java way. A programmer can forget to put his stuff in a block and leak the resource the same as he forgets to use a try-finally. The onus is on the consumer, not the library writer. With C++ RAII the on…

As long as the object is stack allocated or a member variable.

Re: Bjarne Stroustrup – The Essence of C++ [video]

#66
post #60
post #49

Earlier quoted context omitted.

Once things have a name and you can take their address they are no longer an rvalue. It would require a much more sophisticated type system to do this automatically (when you pass a reference to another function, does it capture it?). It would also be non-obvious when you were moving. Think of Java style escape analysis vs C++ stack allocation (implicit vs explicit). There is one case where the compiler will do this…

The argument here is that in the body of the constructor the developer probably doesn't use s, so a trivial analysis of the function can say "oh, it doesn't matter if I destroy s, so in the one place where it is used I'll just move it". It doesn't then matter if it is obvious it happens or not, because the semantics of the program wouldn't be maintained (and honestly, I'd argue it is never quite obvious when what hap…

There are a number of considerations because the compiler can't prove it in general without augmenting the type system or doing whole-program analysis.

Do you allow, but not require, the compiler to do this substitution whenever it can prove a value is never used again? This is unreliable across build options and compilers so it would be unwise to depend on it. There is an opportunity here for a tool that could identify places where you could insert move, perhaps even a -W option for the trivial cases such as above, but I am not convinced the language should allow the compiler to do this.

Do you make it mandatory and add more special cases for the compiler to have to implement? This would require the compiler to track references to make sure they don't get passed to some other function. It would need someone to codify the special cases in the standard and this might be very difficult. It would also be fragile, there would be cases where implicit move used to kick in but some added function call inhibits it even though a move is still the right thing to do.

Re: Bjarne Stroustrup – The Essence of C++ [video]

#67
post #35

Earlier quoted context omitted.

C++11 move semantics eliminates the need of deep copying in most cases and return by value usually is very cheap.

But move semantics only work with temporaries. They don't magically make every object a handle.

For that, there's Java.

Re: Bjarne Stroustrup – The Essence of C++ [video]

#68
post #56

Earlier quoted context omitted.

> My problem with his preferred solution is that I cannot know that Gadget is really a handle to a shared Gadget and not a big fat Gadget value on the stack. The only way of knowing that is to look at the implementation or the documentation. I'd say you do not _need_ to know. If Gadget contains tons of data, it's wiser for it to just put that on the heap, internally. Like std::vector does. As long as Gadget handles (…

I disagree. You have to be absolutely certain at all times whether you're holding on to a reference to a shared data structure or you have your own copy, unless the object is immutable. This is not just a performance thing.

You mean that it's not clear if copying the handle will copy the data or just create another reference? At least in the STL that's kinda clear: vector will copy its elements (if they are pointers, it'll copy the pointers. if they are values it'll copy all the data), shared_ptr will copy the handle pointing to the same shared object, unique_ptr is not copyable and so on.

But agreed, it's opaque when working with third party code. Gotta figure out the conventions.

Re: Bjarne Stroustrup – The Essence of C++ [video]

#69
post #59
post #58

Earlier quoted context omitted.

> It certainly exists in plenty of other languages, but in a non-broken way. C++'s const correctness model is mostly broken, by the way [1]. D's model is a bit more sane [2]. Languages like Haskell or Clojure (AFAIK) make immutability a default. What in particular is broken about const correctness in C++? That things are not const by default? I agree, they should be, but I wouldn't really call that broken. I put cons…

> What in particular is broken about const correctness in C++? The lack of transitivity for one. Const pointers shouldn't be able to modify the pointed objects (that's the default in the D language). The fact that working with non-const-correct libraries is a nightmare (prepare to const_cast a lot!). There are plenty of other things that make this a real PITA to work with on sizable projects with legacy or outside co…

> The lack of transitivity for one. Const pointers shouldn't be able to modify the pointed objects

Are they? I either misunderstand or disagree. The syntax gets a bit silly with pointers, because you can have const pointers and pointers to const (and const pointers to const of course):

    const Foo* foo; // Cannot change *foo, but can change the pointer (e.g. foo = 0)
    Foo* const foo; // Can change *foo, but cannot change the pointer
    const Foo* const foo; // Cannot change *foo or the pointer
> The fact that working with non-const-correct libraries is a nightmare (prepare to const_cast a lot!).

Agreed!

> As far as I know, Common Lisp users have some kind of RAII with macros, but I'm not familiar enough to compare it to C++.

In my experience, the kind of problem RAII is useful for is far less common in Lisps (can only really speak for Clojure). One tends to not encapsulate resource management in any way, so handling it explicitly in the caller is fine. And you can use macros to do something when the scope is excited.

So in Clojure e.g., you can use with-open to do something with a file:

    (with-open [writer (io/writer "foo.txt")]
        (write writer "Hello")))
with-open ensures that the reader is properly closed when the scope is exited or when an exception occurs.

In C++ (or any OOP language I guess), you'd want something like this:

    File foo("foo.txt");
    foo.write("Hello");
So I suppose it depends on the philosophy. For OOP languages, RAII makes a lot of sense IMO.

Re: Bjarne Stroustrup – The Essence of C++ [video]

#70
post #7

Earlier quoted context omitted.

RAII ("classes as resource manager") is one of the nice concepts in C++. My favourite is certainly const correctness. And then there's tons of things that creep me out a bit. Being a multi paradigm language sounds good on paper, but it seems to cause a lot of accidental complexity. The best way to stay sane is probably to pick a certain subset of C++ for your project and stick to that, that's what I tend to do. Then…

C++ const-correctness is weaker than immutability in, say Haskell or Scala.

Can't say anything about Haskell, but what Scala has is less flexible then const correctness in C++ IIRC. You can't have an immutable reference to a otherwise mutable object and then call non-mutating functions on it. It's either fully immutable or fully mutable. CMIIW by all means.
Post reply on HN