Good idea or gimmick: Go-style OO-programming in C++ ?

J

jeti789

Hello,

I lately had a short look at Google's Go language which has only simple support for OOP. My first thought was that a thin OO-layer as in Go on top of C would have been the right size. C++ in some ways comes to heavy on "OO-ness", at least IMHO. Made me think how this kind of thin OO-layer style programming as in Go could be applied to C++.

Sometimes I can get too excited about some "big idea" and after a while I have to realize that I spent too much time on something that wasn't really worth all that fuss. Therefore I would like to ask what other people think about how to do Go-style OO-programming in C++ compared to full-fledged big hammer C++ OO-programming, which appears to me to be oversized (at least for system programming).

Regards, Oliver
 
S

SG

I lately had a short look at Google's Go language which has only
simple support for OOP. My first thought was that a thin OO-layer as
in Go on top of C would have been the right size. C++ in some ways
comes to heavy on "OO-ness", at least IMHO.

Nobody forces you to write big class hierachries in C++. Just go [no
pun intended] with a modern C++ style. Check out Stroustrup's C++11
style talk. Check out Sean Parent's "concept-based polymorphism" talk
for a twist.
 
J

Jorgen Grahn

Hello,

I lately had a short look at Google's Go language which has only
simple support for OOP. My first thought was that a thin OO-layer as
in Go on top of C would have been the right size. C++ in some ways
comes to heavy on "OO-ness", at least IMHO.

What do you mean, more exactly? OO is a term which seems to mean
different things to different people.

It's also a problem that you don't describe the features of Go! you
want us to have opinions on; it's probably something I'm familiar
with, but since I haven't studied Go! specifically I don't know what
"thin OO-layer" means.

/Jorgen
 
J

jeti789

It's also a problem that you don't describe the features of Go! you
want us to have opinions on; it's probably something I'm familiar

with, but since I haven't studied Go! specifically I don't know what

"thin OO-layer" means.



/Jorgen

A class in Go:

type Point struct {
x, y float64
}

Adding a method to a class works like this:

func (self Point) Length() float {
return math.Sqrt(self.x*self.x + self.y*self.y);
}

Note that Length() is defined outside struct Point and the this pointer is handed over as a parameter (named self). A method in Go is public if the first letter is upercase, otherwise it is private.

Inheritance in Go is achieved through delegation, which is built into the language:

type Engine interface {
Start()
Stop()
}

type Car struct {
Engine
}

func GoToWorkIn(c Car) {
c.Start();
c.Stop();
}

In other words: there is no inheritance in Go. The sample code is taken from here: http://www.infoq.com/articles/google-go-primer

All right. You cannot mimic this in C++ and there is no point in bending a language like that. But the question remains whether more than that is really needed - at least for systems programming. In that respect, using C++ asa "C with classes" seems appropriate to me and not just a poor man's way to code in C++. I belive many C/C+ systems develpoer just do it like that without writing a book about it ...

-- Oliver
 
Ö

Öö Tiib

Sometimes I can get too excited about some "big idea" and after a while
I have to realize that I spent too much time on something that wasn't
really worth all that fuss.

That happens with everybody. I have written software over 20 years and
still get excited about some new idiom or some old idea under new angle
I had not thought about. It helps if to make plan at morning "what I will
do today?" and to stick to hit.
Therefore I would like to ask what other
people think about how to do Go-style OO-programming in C++ compared
to full-fledged big hammer C++ OO-programming, which appears to me to
be oversized (at least for system programming).

A language that *requires* garbage collection is bit over-sized for
system programming. C++ programmers tend to (not all of us) prefer RAII
instead.

Go does not have type inheritance, method overloading and/or generic
programming. I can well see how system programming can be done without
those but OO would feel like OO in C. I can do it if I want to but I
feel under-supported by language.
 
S

Stuart

On 02/25/2013, Juha Nieminen wrote:
[snip]
If you want a concrete example of a popular "C with OO" which some people
consider "better than C++", try Objective-C. It consumes more memory and
everything related to classes is slower than in C++. (According to my
measurements calling a member function is approximately 6 times slower
than calling a virtual function in C++. While it's impressive that they
have succeeded in making the calls that fast, considering that they use
messaging, each member function call is still 6 times slower.)

I thought that the invokation mechanism of member functions under
ObjectiveC actually depends on the number of members, so it is not even
constant time but O(log(n)) because ObjectiveC has to use a LUT for
member functions (they can be added at run-time).

However bad ObjectiveC may be, there is one point where it has IMHO an
advantage over C++: I can invoke member functions on objects in debug
mode. So if I have an ObjectiveC container, I can ask it easily for its
current size. This is much more cumbersome under C++.

BTW, I would not say that ObjectiveC is a real programming language as
such. I rather see it as a library for C (or more precisely for C++).

Regards,
Stuart
 
J

jeti789

I thought that the invokation mechanism of member functions under

ObjectiveC actually depends on the number of members, so it is not even

constant time but O(log(n)) because ObjectiveC has to use a LUT for

member functions (they can be added at run-time).

That's right. Objective-C has a runtime engine that carries out method dispatch dynamically. Thus Objective-C has in that way true message passing like Smalltalk, it is modeled after, and no function invokation as in C/C++ and Java (in Java only virtual methods are dispatched at runtime).

-- Oliver
 
R

Rui Maciel

Hello,

I lately had a short look at Google's Go language which has only simple
support for OOP. My first thought was that a thin OO-layer as in Go on top
of C would have been the right size. C++ in some ways comes to heavy on
"OO-ness", at least IMHO. Made me think how this kind of thin OO-layer
style programming as in Go could be applied to C++.

Nothing stops you from writing C++ code that follows that particular style.
Or even C.


Therefore I would like to ask what other people think
about how to do Go-style OO-programming in C++ compared to full-fledged
big hammer C++ OO-programming, which appears to me to be oversized (at
least for system programming).

There is no difference. Go doesn't support inheritance, and therefore it's
limited in that regard. That's it.


Rui Maciel
 
S

Stefan Ram

Öö Tiib said:
A language that *requires* garbage collection is bit over-sized for
system programming. C++ programmers tend to (not all of us) prefer RAII
instead.

RAII supports automatic storage duration,
but not dynamic storage duration. So it has
another scope.
 
Ö

Öö Tiib

RAII supports automatic storage duration,
but not dynamic storage duration. So it has
another scope.

The smart pointers (like std::auto_ptr, std::unique_ptr and std::shared_ptr)
are for controlling ownership of dynamically allocated objects.
 
J

Jorgen Grahn

Whenever someone has the idea of making a "better, light-weight C++",
what results is a language that produces less efficient and more memory
consuming executables, and which is a lot more rigid from the programmer's
point of view. This is the invariable result because such people always
think that:

1) Handling objects by value is way too problematic (because it makes ....
2) Classes must always be dynamically bound, because that's OO, and it ....
3) They have been taught through FUD that multiple inheritance is ....
4) Likewise they have been taught through FUD that C++ templates are
....

Nice satire (and I agree with it), but surely you have Java in mind.
Are you saying Go fell into the same trap?

/Jorgen
 
J

Jorgen Grahn

A class in Go:

Thanks, although the example gives a very incomplete picture.

....
In other words: there is no inheritance in Go.
All right. You cannot mimic this in C++ and there is no point in
bending a language like that. But the question remains whether more
than that is really needed - at least for systems programming. In that
respect, using C++ as a "C with classes" seems appropriate to me and
not just a poor man's way to code in C++. I belive many C/C+ systems
develpoer just do it like that without writing a book about it ...

Well, I do. I very rarely use inheritance and virtual inheritance --
roughly once a year. Basically when the only alternative is function
pointers. I don't resent using it; I just seem to see a need more
seldom than many others do.

So if you remove that, do you have "C with classes"? I don't know. I
know what I cannot live without, though:
- RAII
- objects as values with the same semantics as builtin types
- static typing
- function and operator overloading
- templates
- const

C only has some of those. C++ exists now, and has all of them -- plus
inheritance, when even I see that it's needed.

/Jorgen
 
D

Dombo

Op 25-Feb-13 8:03, Juha Nieminen schreef:
Whenever someone has the idea of making a "better, light-weight C++",
what results is a language that produces less efficient and more memory
consuming executables, and which is a lot more rigid from the programmer's
point of view.

In case of Java that is true, but there are other less fascistic
languages that don't insist on putting the application programmer in a
straight-jacket.

I don't really see Java (or C# for that matter) as a "better,
light-weight C++", but rather as programming languages with a different
goal and scope in mind. The closest thing that seems to be intended as a
"better, light-weight C++" is the D programming language. I'm curious
how you feel about that language.
This is the invariable result because such people always
think that:

1) Handling objects by value is way too problematic (because it makes
things like automatic garbage collection a lot more difficult, breaks
pure OO because not all objects may be dynamically bound, etc.) which
means that classes must only be instantiable dynamically and handled
through references.

Both Java and C# can have objects on the stack. In case of Java only
primitive types (such as int), in case of C# also user defined types
(struct) can be placed on the stack. So I don't believe that GC implies
that "handling objects by value is way too problematic". It is more of
language design choice/philosophy; does the language designer feel that
he should decide what is "good" for the programmer, or does the language
designer trust the judgment and intellect of the programmer.
Given how slow the standard libc allocator is, this
means that creating objects will be at least 10 times slower than how
it is when in C++ you instantiate them on the stack or as an array.
They also consume more RAM (because the memory allocator always needs
to allocate extra memory for its bookkeeping data.)

GC language implementations that use a generational collection scheme
(such as Java and C#) don't use libc for dynamic allocations; the new
statement with these implementations has much lower overhead that the
typical C++ new implementation. Basically the only thing that needs to
be done is to check if sufficient space is available in the current
generation and if so increment a pointer. See also:
http://www.ibm.com/developerworks/java/library/j-jtp09275/index.html
2) Classes must always be dynamically bound, because that's OO, and it
makes the behavior of classes more consistent (and because of point #1
above, it's now possible to enforce that.) That's certainly true, but
it also means that all objects are now larger by at least the size of
a pointer, no matter how simple and small they would otherwise be, and
even if no dynamic binding is used in them at all. It also makes compiler
optimizations more difficult because the compiler cannot now inline any
member functions because it cannot know if they are actually dynamically
bound.

Not always. In Java every method is virtual (except static, and you can
mark a method as final), in C# it is the same as C++; methods aren't
virtual unless you tell it is virtual. Also JIT compilers have been
known to do rather clever tricks to inline virtual methods.
3) They have been taught through FUD that multiple inheritance is
eeeeeevil and scary, and therefore it must not be supported. Therefore
they will implement a crippled version of multiple inheritance (which
they will call "interfaces"), while still denying the fact that the
language *does* support multiple inheritance (just a crippled version
of it.) This forces code repetition from the programmer's part in many
cases, making the language more rigid.

I understand that the main reason not to add support for it in Java that
the language designers found it too hard to implement.
4) Likewise they have been taught through FUD that C++ templates are
eeeeeevil and scary, and therefore they must not be supported. Therefore
they will implement a crippled version of templates (which they will call
"generics"), while still denying the fact that the language has templates
(just a crippled version of them.) No vectors of ints or anything like
that supported, for no obvious or rational reason (other than that C++
templates are "evil".) This makes the language more rigid and less
efficient.

Though C++ templates are extremely powerful, if you go beyond containers
of type T I cannot say they are the most intuitive feature of C++ or
well understood by the average C++ programmer. I guess generics fulfill
80% of the need, at significantly less than 20% of the language
complexity. I can imagine why a language designer makes such a trade-off
(even though I do sometimes miss the power C++ templates when
programming in a language other than C++).
If you want a concrete example of a popular "C with OO" which some people
consider "better than C++", try Objective-C. It consumes more memory and
everything related to classes is slower than in C++. (According to my
measurements calling a member function is approximately 6 times slower
than calling a virtual function in C++. While it's impressive that they
have succeeded in making the calls that fast, considering that they use
messaging, each member function call is still 6 times slower.) Of course
there is no MI nor templates, and the classes themselves have multitude
of problems (such as no constructors nor destructors, other than by
naming convention and manually having to call them.)

After reading this rant I got the impression that it is based on Java
experience from well over a decade ago.

I learned C++ 20 years ago, and used it for at least 90% of the projects
I have done in my career. On occasion I use other languages like Java,
C#, Python or whatever language appears to be the most suitable choice
for the problem at hand. C++ is almost always at least a reasonable
choice, but certainly not always the best choice.

When I hear Java fanboys ranting about C++, it is often quite clear they
are rather ignorant as far as (modern) C++ is concerned. Likewise when
C++ fanboys start whining about this language does not support
this-or-that C++ feature so it must suck. The big mistake many people
make is trying to treat the other language as the language they know
best, rather using the idioms and conventions typical for the language.
A language feature cannot be considered in isolation, you have to look
at the bigger picture. In C++ I use RAII a lot, and in my opinion the
language would be pretty useless without it (when using exceptions). And
though I miss RAII in other languages, I don't miss it as much as one
could expect due to things like garbage collection and finally, using
and lock statements. Python doesn't support templates, but then again
duck typing pretty much eliminates the need. In Java and C# you have
reflection, which can be quite useful on occasion, but C++ doesn't have
anything that come close to that...etc.

As far as performance is concerned, C++ gives you the most control, and
if you need that control C++ is the way to go. But many times
performance is not that critical, good enough is good enough and other
considerations are more important. My experience with languages like C#
are in real life not that much slower for most tasks (except for startup
time). Quite often the speed of an application is more limited by I/O
than by raw processing speed.
 
S

Stefan Ram

Dombo said:
Though C++ templates are extremely powerful, if you go beyond containers
of type T I cannot say they are the most intuitive feature of C++ or
well understood by the average C++ programmer.

I think, often programmers prefer to learn and use features
of a language they also know from other languages and a
style of code that could be translated to some degree into
another language. They often shy away from using unique
features of a language, however advantageous they might be.

Writing in a idiomatic style often needs special training.

For example, when a Pascal programmer sees

if( d )

, he seems to think: »You cannot write this is Pascal!
So it is bad style! Therefore, even in C, one should write

if( d != 0 )

. Eventually, I will have to translate my C program into
Pascal (when the world finally understands that Pascal is
better) and then it will be much easier this way.«
 
J

Jorgen Grahn

Op 25-Feb-13 8:03, Juha Nieminen schreef: .... ....
I don't really see Java (or C# for that matter) as a "better,
light-weight C++", but rather as programming languages with a different
goal and scope in mind.

That is probably true today. In the early days of Java though, the
message real-life programmers heard was "now you C programmers out
there can do real object-oriented programming without bothering with
that failed language C++".

At that time, in my area of work, older "academic" languages like
Smalltalk were unavailable. Scripting languages weren't mainstream yet
and gcc was not considered good enough for serious work. The offering
from Sun was very tempting.

[snip lots of good stuff]

/Jorgen
 
J

jeti789

That happens with everybody. I have written software over 20 years and
still get excited about some new idiom or some old idea under new angle
I had not thought about. It helps if to make plan at morning "what I will
do today?" and to stick to hit.

Okay, I see what you mean ;-). But the internet is really a great place to talk to people that have some general understanding you can't find in everyprogramming shop...
A language that *requires* garbage collection is bit over-sized for
system programming. C++ programmers tend to (not all of us) prefer RAII
instead.

That might be true. I can't say since being an application programmer I don't have the knowledge about systems programming to be able to judge. However, there are GC's nowaydays with stop-the-world times below 10 ms like the train GC, which is also available in the JVM as a choice. This might be good enough for *some* applications on systems-level and worth the saved time in writing code for allocation and deallocation. Seems like the guys at Google developing Go think a GC is not a problem for their purposes. D has a garbage collector which you can "over-rule" (manually deallocate some object). I think the latter is a good approach for many things.
Go does not have type inheritance, method overloading and/or generic
programming. I can well see how system programming can be done without
those but OO would feel like OO in C. I can do it if I want to but I
feel under-supported by language.

The lack of parameterized types is a real problem IMHO. Programming with variant records or something is also in system-programming not flexibel enough. As what Go is concerned it is probably better to wait for some years till they have gained experience about its usability and have learned on whichthings they need to back up on. But I see some nice ideas in their language design, nevertheless.
BTW, I would not say that ObjectiveC is a real programming language as
such. I rather see it as a library for C (or more precisely for C++).

Well, it has a real runtime engine ;-). It looks more like an extension of C based on macros, e.g. all that keywords that start with "@" seem to be a hint to the compiler that some non-C code is comming now.
They have been taught through FUD that multiple inheritance is bad

I have spent about 20 years with languages that do not support multiple inheritance (Smalltalk and Java) and I would say that single inheritance is really a problem. You inherit from the class from which you can re-use most of the functionality. For the other classes that in some cases you should also inherit from you create an inst var and make use of delegation. This fills your class with a lot of code that just does forwarding to the delegate and delegation does not give you access to some class' protected methods and vars. Language built-in delegation as in Go or Kotlin is really nice. However, I prefer the problems out of multiple inheritance compared to the problems with single inheritance. Leave it to the developer to make use of multiple inheritance with caution and care but don't leave him in the mud.
GC language implementations that use a generational collection scheme
(such as Java and C#) don't use libc for dynamic allocations; the new
statement with these implementations has much lower overhead that the
typical C++ new implementation.

Yes, GCs are very well optimised towards creating objects efficiently. In agenerational GC many objects won't enter the mature object space and therefore don't make it onto the heap from the beginning.
I understand that the main reason not to add support for it in Java that
the language designers found it too hard to implement.

MI was very controversial at the time Java was developed, because of the diamond problem and other problems. This is why the Java guys decided to be careful with it. Other people like Niklaus Wirth with Oberon have decided before in the same way. Stateful traits as in Scala are one way out, althoughthey are not without problems, either. You can combine stateless traits and delegates in Kotlin and you get almost the same as MI and it is very clean and simple, see the chapter named "Delegation" here: http://confluence.jetbrains.com/display/Kotlin/Classes+and+Inheritance

-- Oliver
 
Ö

Öö Tiib

That might be true. I can't say since being an application programmer I
don't have the knowledge about systems programming to be able to judge.
However, there are GC's nowadays with stop-the-world times below 10 ms
like the train GC, which is also available in the JVM as a choice.

10 ms is impossible to notice for human. However if your system controls
some engine or laser at high speeds then such unpredictable delay can break
the device. Notice '*requires*' above. GC was proposed (and I understand
it still is proposed) as *optional* for C++. It did not make it into
C++11 but history does not end there. Currently one needing GC can add
it by adding some open source library that implements GC.

You seem to be person who is experienced and likes GC. The publications
of such people are missing from market! Several use GC with C++ but no
quality "how to use" material is floating around. The few that there is
is of low quality. Gather it together and publish / start selling. Do
not care about flames of proponents of pure, GC-free C++. Just ignore
them. Your effort can aid GC into C++.

I am firm follower of RAII idiom (last resource leak that I discovered
in my code was 8 years ago), so I can't help there much, I see currently
no purpose for GC whatsoever since RAII behaves more predictably
while being both as painless and as efficient as GC (but I admit that I
can be still wrong).
This might be good enough for *some* applications on systems-level and
worth the saved time in writing code for allocation and deallocation.
Seems like the guys at Google developing Go think a GC is not a problem
for their purposes. D has a garbage collector which you can "over-rule"
(manually deallocate some object). I think the latter is a good approach
for many things.

Yes, GC should be no more than *optional* for any languages that aim to
be useful for solving problems in real time systems. C++ certainly aims
to be such a language.
The lack of parameterized types is a real problem IMHO. Programming with
variant records or something is also in system-programming not flexible
enough. As what Go is concerned it is probably better to wait for some
years till they have gained experience about its usability and have
learned on which things they need to back up on. But I see some nice
ideas in their language design, nevertheless.

That is normal trend. Languages evolve. You never know into what that Go
evolves. My answer was that for me OOP is insufficiently supported in Go
right now.

OTOH C++ has evolved into monster of unrivaled complexity if to
take it as whole. That is the cost of being multi-paradigm language.
Why to use whole C++? No reason. Every C++ team starts from choosing
coding standards that specify what language features they do not use in
current project and limitations how to use and format the features that
they do use.

About that process there are lot of books. Lot of coding standards
have been freely and commercially published.
http://www.sourceformat.com/coding-standard.htm
There are even automated tools that check code conformance to most
popular coding standards but serious ones are commercial tools ATM.
The few that I sometimes use to speed reviewing others code are
bloody expensive too.

Your goal seems to be also to enforce usage of some subset of C++. I
would start from writing a "coding standard of Oliver" (see the ones
in link) and static code analysis tool that checks for following the
standard. If you spread it as free there will probably be developers
who like exactly that subset and pick it up. If you gain fame you can
later commercialize the whole idea and get rich and famous. Just send
me e-mail with "thanks" after that. ;)
 
S

Stefan Ram

Öö Tiib said:
I am firm follower of RAII idiom (last resource leak that I discovered
in my code was 8 years ago), so I can't help there much, I see currently
no purpose for GC whatsoever since RAII behaves more predictably
while being both as painless and as efficient as GC (but I admit that I
can be still wrong).

I'd like to read a book/chapter/article especially about
rules to follow to avoid memory errors (that is, both leaks
or invalid accesses) in C++, both for automatic and for
allocated storage. Maybe someone is aware of something like
this? (I am aware of some GotW questions about exception safety.)

In C, I can easily summarize. AFAIK

- Do not pass pointers to automatic storage upwards
(i.e., beyond its life time).

- Do not access pointers intended for dynamic storage
that
- do not point to memory obtained from a
successful call to malloc or equivalent
- already have been released by free or
equivalent

- For every successful malloc eventually there
should be exactly one corresponding free
(unless that is a short-lived program that will
terminate soon anyways)

But C does not have containers, exception, references,
smart pointers, ...
 
S

SG

  I'd like to read a book/chapter/article especially about
  rules to follow to avoid memory errors (that is, both leaks
  or invalid accesses) in C++, both for automatic and for
  allocated storage. Maybe someone is aware of something like
  this? (I am aware of some GotW questions about exception safety.)

I guess it can be summarized as "Appreciate RAII" where RAII refers to
the concept of delegating responsibilities (like resource management)
from yourself as a programmer to objects that either live in automatic
memory or are themselves managed by one or more other objects that
live in automatic memory or ... you get the idea. :) You can imagine a
graph which represents
these responsibility/ownership relations between objects/resources. It
should be acyclic and its roots should be objects living in automatic
memory. This means that there won't be any "owning raw pointers".
That's how you at least solve leaking issues.

Avoiding invalid accesses is about making sure that you don't use a
pointer (or reference) whose pointee ceased to exist. This is a bit
trickier I guess and I don't think that there is a general approach
that's applicable in every situation (even less so compared to RAII).
Holding on to a "non-owning" pointer might be perfectly reasonable in
some programs. Examples for "non-owning" pointers are raw pointers and
objects of type std::weak_ptr<T>. The nice thing about weak pointers
is that you can actually detect whether the pointee still exists or
not. But of course, this relies on the pointee being managed by a set
of std::shared_ptr objects which might be overkill in some cases. For
example, I would prefer std::unique_ptr over std::shared_ptr as an
"owning pointer". In probably most cases you don't really nead to
share ownership of a dynamically allocated object, so unique_ptr would
be sufficient. The downside obviously is that you don't get to check
whether this dynamically allocated object still exists if all you have
is a raw pointer.
  In C, I can easily summarize. AFAIK

    - Do not pass pointers to automatic storage upwards
      (i.e., beyond its life time).
    - Do not access pointers intended for dynamic storage
      that
        - do not point to memory obtained from a
          successful call to malloc or equivalent
        - already have been released by free or
          equivalent
    - For every successful malloc eventually there
      should be exactly one corresponding free
      (unless that is a short-lived program that will
      terminate soon anyways)

  But C does not have containers, exception, references,
  smart pointers, ...

For C++ I would write:

- Learn about and appreciate RAII. This includes things like

- Prefer containers over hand-written "pointy" data structures.

- Don't use raw pointers and references for things you
would have to delete manually later.

- Use std::vector instead of new[]

- Whenever you feel the need to dynamically allocate something
stop for a minute and ask yourself whether there is a better
way.

- If you still feel the need to dynamically allocate stuff,
delegate the responsibility for its deletion to an object of
type unique_ptr or shared_ptr (or something like that).

- Keep in mind that if you feel the need to manually call
delete or delete[] you it's very likely that you did
something wrong.

- Don't access things that ceased to exist.

- shared_ptr/weak_ptr allows you to detect this for
dynamically allocated objects.


Perhaps it's a good idea to somehow replace unique_ptr<T> and T* with
shared_ptr<T> and weak_ptr<T> for the debug mode so that you can
terminate with an assert in case of a dangling pointer.


Cheers!
SG
 
Ö

Öö Tiib

I'd like to read a book/chapter/article especially about
rules to follow to avoid memory errors (that is, both leaks
or invalid accesses) in C++, both for automatic and for
allocated storage. Maybe someone is aware of something like
this? (I am aware of some GotW questions about exception safety.)

I can summarize it like that for C++:

* As pointers use only smart pointers Prefer std::unique_ptr and
std::shared_ptr (with its weak brother). std::auto_ptr has odd
semantics but is otherwise fine too.

* You may pass references to smart pointers, but you may not store
those.

* Never dereference a pointer without comparing it with 'nullptr'
first. Always check the results of std::weak_ptr::lock().

* Never take out raw pointer from smart pointer unless interfacing
with module written in C.

* Use keyword 'new' only in context of initializing or assigning
to std::unique_ptr or even better write 'make_unique' template
(it is just missing from standard ATM) and do not ever use
'new' in C++ code.

* Never use keyword 'delete'.

* Never use dynamic arrays, use std::vector. Prefer iterators to
indexes. Use at() instead of operator[].

* Never use static arrays, use std::array. Prefer iterators to
indexes. Use at() instead of operator[].

* Store references only on case of composition. Component may store
reference of composite.

* Every object pointed at with std::shared_ptr should have one and
only one real owner. Co-owners must have (accessible to real owner
ways to signal them) that the object is invalid and should be
released.

* Never use dynamic storage manipulation from C or operating system
(malloc, realloc, strdup, GlobalAlloc, SysAlloc, VirtualAlloc). Use
*very* well-tested libraries that do it.

See ... somewhat more complex than for C, but C++ is more complex too.
Most of these rules are simple to statically analyse in code and so
most modern repositories can be therefore guarded against committing
"illegal" C++ code.

I see that all the rationale is missing and the rules feel probably
too harsh for many without rationale, but so what? Works for me. ;)
If you suggest I should write a book with rationale then I have to
first find someone who translates my babble into valid English. :D

In modern world that is too few. Without addressing the problems
with concurrency (how to fight race conditions without deadlocks)
this is barely half of "illegal" accesses to memory.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,011
Latest member
AjaUqq1950

Latest Threads

Top