
C++'s Rule of Zero - adamnemecek
https://turingtester.wordpress.com/2015/06/27/cs-rule-of-zero/
======
Animats
This is why it's time to move to Rust. Trying to retrofit single-ownership
semantics to C++ never quite works. It _almost_ works. But not quite.

C++ has been trying to get single-ownership semantics to work right for almost
two decades. "auto_ptr" went through three standards revisions before the C++
standards committee finally gave up and dropped it. Now there's unique_ptr,
where, after sprinkling on some move semantics, _almost_ works, with fewer
holes than auto_ptr.

Getting this right needs a borrow checker, like Rust's. Now that borrow
checking has finally been figured out, there's a way out of this mess. Trying
to do borrow checking via the type system just doesn't work out well.

~~~
coliveira
People who write code in C++ are not doing this because it is fun or just
because it is the latest buzzword. They do it in C++ because it is the
language that supports the billions of lines of code in their industry, while
providing a path forward through new standards and libraries. In summary, code
written in C++ will not move to other languages because there is no need for
that. The best opportunity for competitors is to write their own new systems
and replicate what C++ already has. Not even Java has been able to do that up
to this moment. And while it is possible, it will take a long time.

~~~
marcosdumay
Java is one of the least capable contenders at this point.

All those thousands of lines of C++ code, you can easily use them in any
language you choose, except for Java.

~~~
GFK_of_xmaspast
It's actually reasonably easy, you just write a shim that can be linked as
'extern "C" {}' and then use jni. (I find it much easier than, for example,
cython)

~~~
santaclaus
This even works for Fortran.

------
kazinator
If you don't write a destructor, and the class needs one, the compiler will
write one for you. Same with some of the other special functions.

The rule might be expressed as "try to write classes that are adequately
served by the compiler-generated special functions" (which the compiler will
write consistently).

If all your member objects have destructors, there should be nothing left to
do. The generated destructor recurses over these and that is that. So writing
a custom destructor is for cases when something additional needs to be done
because some members don't clean themselves up, or there is some other issue
even if they all do. The Rule of Zero seems to be saying that these cases tend
to be code smell.

Anyway, of course you have to write (or at least declare) a destructor if you
need a virtual one, at the bottom of a class hierarchy.

    
    
      ~MyAbstractBase() = 0;
    

The language-supplied destructor will not be virtual, and certainly not pure
virtual.

~~~
pbsd
You cannot just declare the destructor of a base class, since it will get
called by the derived class destructors and linking will then fail. But you
_can_ write out an implementation for a pure virtual function, which will
still keep the base class uninstantiable:

    
    
      virtual ~AbstractBaseClass() = 0;
      ...
      AbstractBaseClass::~AbstractBaseClass() { }

~~~
anon4
Huh. Does that mean I can write

    
    
        class A {
        public:
        virtual void foo() = 0;
        };
        void A::foo() {}
        class B: public class A {};
        B b;
        b.foo();
    

and that will work?

~~~
pbsd
No, it will complain that A::foo is pure virtual, and that B _must_ implement
`foo`. However, if you define in B the method `void foo() { A::foo(); }`, it
will work. In destructors this happens implicitly.

There was an old Herb Sutter GotW about this:
[http://www.gotw.ca/gotw/031.htm](http://www.gotw.ca/gotw/031.htm)

------
MichaelMoser123
> "classes should not define any of the special functions (copy/move
> constructors/assignment, and the destructor) unless they are classes
> dedicated to resource management."

All C++ classes are dedicated to managing the memory resource that they are
allocated on, am i missing something?

~~~
goldfire
The rule is saying that a class which does explicit resource management should
be doing _only_ resource management and have no other behavior. In other
words, only wrapper classes should manage the resource they wrap, and
(ideally) no other resource management should exist. That keeps the management
work out of the way of other classes.

~~~
jblow
And this leads to code that is either too complex, too inefficient, or both.

I mean it's fine if you are competing with Python or something ,but if you
actually care about perf this is never going to work. But of course anyone
wanting to coin a "Rule of X" doesn't want to see a problem in its full
context, they just want to be able to pretend to have a solution well enough
that they can at least fool themselves. Etc, etc.

------
jkasdjfa
"Example" will be move only if any of its members are move only. Adding copy
semantics to a move only type was stupid to begin with.

