Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Seems to be a very old list or it might tell you this: If you start a new project, don't use C++.

http://harmful.cat-v.org/software/c++/ tells you everything.



The link you have is also old - most of the issues reported there are not valid anymore with C++11.

BTW, at least for Windows 8 now Microsoft recommends you to start new projects in JavaScript or C++ (in this order).


C++11 introduces new problems. Programmers are expected to know how a lexical closure should capture variables from the enclosing scope -- should it be by reference, or by value? Programmers are also expected to know that when they capture by reference, sometimes they are really supposed to capture by value but with smart pointers (and of course, they are expected to know which kind of smart pointer they need). Instead of fixing the double exception fault, C++11 just punts on the issue and says that no exceptions are ever allowed to propagate out of a destructor (which is another way of saying, "destructors must never signal errors, even for things that are correctable like running out of disk space).

That Microsoft would recommend JavaScript or C++ is unsurprising, considering how much business those languages have generated for them and how many programmers who support the Windows ecosystem are only comfortable in one of those two languages.


[deleted]


Yes, they fixed many things - and that's good. The alternative is to create a new programming language every year, just to discover it breaks down somewhere else (ask Twitter about Ruby).

Memory management is needed for C, but not for C++ or ObjectiveC. I worked years on large C++ systems (>300 developers) without using "new" or "delete".

Whenever I develop in Scala or other GC language, I still miss the deterministic destructors. For memory it is OK to be freed anytime, but there are other resources (GPU, file, TCP port) that you still have to manage manually and it needs to be freed right away. It's trivial to write in C++, but I never saw a failsafe C# implementation.


C++ "smart" pointers do not free you from thinking about memory management; the fact that you are expected to choose between shared_ptr and weak_ptr should be enough to tell you that. Unlike languages with a garbage collector, C++ requires programmers to spend their time trying to figure out if they will create a cyclic data structure, and then also to figure out where that cycle should be broken. That is moderately better than having to figure out when it is OK to free memory and when it is necessary to free memory, but only moderately. Let's put it this way: if you were writing a doubly-linked list, where would you put the shared_ptr, and where would you put the weak_ptr (or would you just give up, use "dumb" pointers, and have destructors free memory)?


It's not necessarily about "smart" pointers. It can be just the use of stack - for all objects.


Can you expand on using C++ without "new" or "delete"? I'm curious. I'm learning C++11 now and I'm having trouble seeing how you could do that.


In addition to what is talked about below, using value semantics (with mutable or immutable objects) can be helpful. Lots of types can be given value semantics and end up more efficient (most people think copying == less efficient, always) due to the lack of pointers and the locality destroying/cache unfriendliness they introduce. In my experience if you see new/delete in C++ code you should be immediately questioning who owns that object, how it is shared and how/when it is destroyed. I can't even count the number of times I have seen one object new up something and then share a raw pointer with N other objects, who then either have to coordinate who calls delete or, the creator itself does so, and you may have use-after-free issues. unique_ptr and shared_ptr, or their moral equivalents, help avoid most of these issues. As a bonus shared_ptr enables weak_ptr, which can also be very handy for non-owning users and breaking cycles in object graphs.


If you use smart pointers in your code (std::unique_ptr, std::shared_ptr), you will rarely have to call delete. A unique_ptr for example owns an object through a pointer; the pointer is automatically deleted when the unique_ptr goes out of scope. shared_ptr retains shared ownership through reference counting; the pointer is deleted when the reference count reaches zero.


So, in your code you would never write this:

    class Foo {
      ...
    private:
      Bar *myBar;
      Baz *myBaz;
    };
You would instead always do something like this:

    class Foo {
      ...
    private:
      shared_ptr<Bar> myBar;
      unique_ptr<Baz> myBaz;
    };
Is that right?


Using your example let's assume myBar and myBaz are _owned_ by Foo. Before C++11 you would typically do this:

   class Foo {
   public:
      Foo() : myBar(0), myBaz(0)
      {
         myBar = new Bar;
         myBaz = new Baz;
      }
      ~Foo
      {
         if (myBar) delete myBar;
         if (myBaz) delete myBaz;
      }
   private:
      Bar *myBar;
      Baz *myBaz;
   };
In C++11, the above could be written like this:

   class Foo {
   public:
      Foo() : myBar(new Bar), myBaz(new Baz)
      {
      }
   private:
      std::unique_ptr<Bar> myBar;
      std::unique_ptr<Baz> myBaz;
   };
You don't need to call delete because the unique_ptr destructor will do it for you.

You would only need to use shared_ptr when ownership is shared among multiple objects. A shared_ptr holds a reference counter that is incremented every time it is copied, and decremented every time it is destroyed or re-assigned. When the reference counter reaches zero, the pointer is automatically deleted.


Pre C++11 you would use a scoped_ptr in that scenario. And for the record, the conditionals in that destructor are redundant, deleting a null pointer does nothing.


And once they get around to adding std::make_unique (or you add it to your codebase yourself), you won't even need new there either.


You can also use:

    Bar myBar;
    Baz myBaz;


Depends on the situation. I'm asking about pointers specifically because I have a situation in which the lifetime of the property is different than the lifetime of my object.


It always depends on the situation. :)

C++ encourages hiding the data inside an object, in which case the lifetime of the data will be the same.

Sometimes the wrapped data has to be exposed directly, e.g. graphics pipeline needs direct access for performance reason. Even in that case it is useful to have a class. For example the VTK image reader class will handle a lot of bit depth related differences transparently. Makes it possible to store different image types with different bit depth in a single container and most of the access is still trough interface (e.g. GetWidth).


My first decent sized program is to parse a strange file format that contains multiple tables into a DOM-like representation, and then output that DOM to CSV.

What I have so far, is a SAX-like event-driven parser that works, and I have a CSV writer that works, and I have hooked them together, and that works. I managed to avoid using pointers for that chunk of code.

For the DOM building portion, I need to allocate table and row objects while I'm getting events, and since I don't know ahead of time how many of each I'm going to have, I more-or-less must have a pointer to "the current" table, and then when that table is complete or I run out of document I can add it to the document object. So the lifespans are not identical anymore: the builder is going to have to allocate tables as it builds and probably rows as well.

At the moment I'm using pointers, and I just make a new table or row when appropriate and then add it back to the container. But this is a little messy because the containers are, you know, vector<table> and vector<row> and they don't need to think in terms of pointers for that reason. So I wind up passing currentTable and currentRow to the add methods, which probably makes copies on the stack.

I am sure that somebody with more C++ experience would see the right way to do this. My experience is largely with conventional OO languages (i.e. memory managed) and functional programming languages. So I'm a little lost on how to structure this.


Yes.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: