Article on possible improvements to C++

Discussion in 'C++' started by sfuerst, Nov 19, 2009.

  1. sfuerst

    sfuerst Guest

    Hello, I've written an article at http://locklessinc.com/articles/10_problems_with_c /
    that is unfortunately way too long to post here, detailing ten
    perceived problems with C++, together with some possible solutions.
    The list kind of looks like the typical one brought up by novices,
    complaining about things like exceptions and multiple inheritance.
    However, the actual issues discussed tend to be more subtle and low-
    level than what you are probably thinking. In particular, none of the
    "problems" are complaints about the existence of features, just on
    their current syntax, or typical underlying implementation.

    The 10 problems are:
    1) The "new" keyword.
    2) Exceptions
    3) Implementations of Multiple Inheritance
    4) Member Pointers and Member Function Pointers
    5) 0 is NULL
    6) Operator Overloading
    7) Template Syntax
    8) The "export" Keyword
    9) Classes verses Structs
    10) Barriers

    Unfortunately, some of the solutions aren't particularly good. (The
    worst one probably is a replacement syntax for the new keyword.)
    However, constructive criticism has to start somewhere.

    Any comments, or flames are welcome. :)

    Steven
     
    sfuerst, Nov 19, 2009
    #1
    1. Advertising

  2. * sfuerst:
    > Hello, I've written an article at http://locklessinc.com/articles/10_problems_with_c /
    > that is unfortunately way too long to post here, detailing ten
    > perceived problems with C++, together with some possible solutions.
    > The list kind of looks like the typical one brought up by novices,


    He he, it certainly does. :)

    But kudos (speling?) to you for writing it up.

    For that can both help you and help many others.


    > complaining about things like exceptions and multiple inheritance.
    > However, the actual issues discussed tend to be more subtle and low-
    > level than what you are probably thinking. In particular, none of the
    > "problems" are complaints about the existence of features, just on
    > their current syntax, or typical underlying implementation.
    >
    > The 10 problems are:
    > 1) The "new" keyword.


    OK, there's much wrong.

    First, "Unfortunately, the new keyword doesn't allow [...] an override." is
    wrong. You override the allocation aspect by defining operator new (and/or
    operator new[], which is the allocation function, which can be overridden per
    class as well as overriding the global default (where, to boot, you can override
    the action taken on allocation failure via set_new_handler). And you can
    "override" the initialization action by defining suitable constructors.

    Second, this is wrong: "A second problem with the new keyword is that it
    combines two different operations in one. The first is to allocate memory, the
    second is to initialize it. This combination means that initializing an array is
    impossible to do with anything other than the default constructor."

    'new' is designed to very strongly couple allocation and initialization, with
    automatic rollback. It's extremely tricky to do manually, that is, to do it
    correctly without language support. If C++ didn't have 'new' to do it, it would
    need some other mechanism to do it, which would then be used instead of 'new'.

    Also, it's wrong that it's impossible to initialize an array in other ways than
    using a default constructor.

    For example,

    std::vector<int> a( 42, 999 );

    Third, this is wrong: "Similarly, destructing an array with the delete[]
    operator is inefficient.". delete[] is designed for maximal efficiency. The
    trade-offs made to achieve that efficiency, in particular that the programmer
    must supply the knowledge of whether it's delete or delete[] (just in order to
    save a byte or two of memory!) is a problem, but the efficiency is not. :)

    Now, to your (rhetorical) question, "If all backwards compatibility were thrown
    out, how could construction, initialization, and memory allocation be better
    done, (paying particular attention to orthogonality)?"

    This is addressed in C++0x, which unfortunately seems to be a long way from
    ratification, but still.

    It's an initialization syntax based on curly parentheses initializers.


    > 2) Exceptions
    > 3) Implementations of Multiple Inheritance
    > 4) Member Pointers and Member Function Pointers
    > 5) 0 is NULL
    > 6) Operator Overloading
    > 7) Template Syntax
    > 8) The "export" Keyword
    > 9) Classes verses Structs
    > 10) Barriers
    >
    > Unfortunately, some of the solutions aren't particularly good. (The
    > worst one probably is a replacement syntax for the new keyword.)
    > However, constructive criticism has to start somewhere.
    >
    > Any comments, or flames are welcome. :)


    I skimmed the section on Exceptions, it is also full of misconceptions. But
    those are more arguable, questions more of design than how things work
    technically. However, others will probably chime in for the rest (also about
    what's wrong with section 2), and I hope my comments on section 1 help.


    Cheers,

    - Alf
     
    Alf P. Steinbach, Nov 20, 2009
    #2
    1. Advertising

  3. sfuerst

    maverik Guest

    On 20 ноÑ, 03:52, "Alf P. Steinbach" <> wrote:
    >> * sfuerst:
    >> This combination means that initializing an array is
    >> impossible to do with anything other than the default constructor."


    [skip]

    > Also, it's wrong that it's impossible to initialize an array in other ways than
    > using a default constructor.
    >
    > For example,
    >
    >      std::vector<int> a( 42, 999 );


    I think, he means that 'new' uses default constructor and there is no
    way (AFAIK) to use parameterized constructor with 'new'. Something
    like this

    int *p = new int[3] { 1, 2, 3};

    Of course, I don't know why this may need
     
    maverik, Nov 20, 2009
    #3
  4. sfuerst

    Pavel Guest

    sfuerst wrote:
    > Hello, I've written an article at http://locklessinc.com/articles/10_problems_with_c /
    > that is unfortunately way too long to post here, detailing ten
    > perceived problems with C++, together with some possible solutions.
    > The list kind of looks like the typical one brought up by novices,
    > complaining about things like exceptions and multiple inheritance.
    > However, the actual issues discussed tend to be more subtle and low-
    > level than what you are probably thinking. In particular, none of the
    > "problems" are complaints about the existence of features, just on
    > their current syntax, or typical underlying implementation.
    >
    > The 10 problems are:
    > 1) The "new" keyword.
    > 2) Exceptions
    > 3) Implementations of Multiple Inheritance
    > 4) Member Pointers and Member Function Pointers
    > 5) 0 is NULL
    > 6) Operator Overloading
    > 7) Template Syntax
    > 8) The "export" Keyword
    > 9) Classes verses Structs
    > 10) Barriers
    >
    > Unfortunately, some of the solutions aren't particularly good. (The
    > worst one probably is a replacement syntax for the new keyword.)
    > However, constructive criticism has to start somewhere.
    >
    > Any comments, or flames are welcome. :)
    >
    > Steven

    I am surprised you did not complain about the preprocessor. Ugly and
    powerless. No loops, no procedures, no way to tell a macro from a
    language keyword or name, no way to even insert a newline into macro
    expansion. I wonder why they had to re-invent that particular wheel when
    much superior PL/1 preprocessor had been around since 60s.

    Maybe if C had a good preprocessor there would be no need for those ugly
    templates in C++. And then an average-sized program would not take
    infinity to compile at multi-GHz CPU. And you wouldn't get 9999
    9997-character lines of unreadable error messages for missing a const
    keyword or forgetting to include a header file with yet another overload
    of << operator. All pipe dreams I guess..

    I remember how Turbo-C and especially Turbo-Pascal used to compile on
    5-MHz CPU and can't help crying :)

    How's that for a good flame igniter?

    -Pavel
     
    Pavel, Nov 20, 2009
    #4
  5. sfuerst

    James Kanze Guest

    On Nov 20, 12:52 am, "Alf P. Steinbach" <> wrote:
    > * sfuerst:


    [...]
    > > The 10 problems are:
    > > 1) The "new" keyword.


    > OK, there's much wrong.


    > First, "Unfortunately, the new keyword doesn't allow [...] an
    > override." is wrong. You override the allocation aspect by
    > defining operator new (and/or operator new[], which is the
    > allocation function, which can be overridden per class as well
    > as overriding the global default (where, to boot, you can
    > override the action taken on allocation failure via
    > set_new_handler). And you can "override" the initialization
    > action by defining suitable constructors.


    Not to mention all the things that can be done using placement
    new.

    > Second, this is wrong: "A second problem with the new keyword
    > is that it combines two different operations in one. The first
    > is to allocate memory, the second is to initialize it. This
    > combination means that initializing an array is impossible to
    > do with anything other than the default constructor."


    > 'new' is designed to very strongly couple allocation and
    > initialization, with automatic rollback. It's extremely tricky
    > to do manually, that is, to do it correctly without language
    > support. If C++ didn't have 'new' to do it, it would need some
    > other mechanism to do it, which would then be used instead of
    > 'new'.


    FWIW: you can separate the two actions, by calling the operator
    new function and using placement new for initialization. New
    was introduced, however, precisely because it was felt that the
    separation is a bad thing---it means that you can end up with
    raw memory, that the compiler thinks is a constructed object.
    In all but very exceptional, low level code, this is an error.

    > Also, it's wrong that it's impossible to initialize an array
    > in other ways than using a default constructor.


    That could be considered a default. I'm not sure, but perhaps
    the new initialization syntax in C++0x addresses this as well.

    > For example,


    > std::vector<int> a( 42, 999 );


    > Third, this is wrong: "Similarly, destructing an array with
    > the delete[] operator is inefficient.". delete[] is designed
    > for maximal efficiency. The trade-offs made to achieve that
    > efficiency, in particular that the programmer must supply the
    > knowledge of whether it's delete or delete[] (just in order to
    > save a byte or two of memory!) is a problem, but the
    > efficiency is not. :)


    > Now, to your (rhetorical) question, "If all backwards
    > compatibility were thrown out, how could construction,
    > initialization, and memory allocation be better done, (paying
    > particular attention to orthogonality)?"


    > This is addressed in C++0x, which unfortunately seems to be a
    > long way from ratification, but still.


    > It's an initialization syntax based on curly parentheses
    > initializers.


    Yes, but it doesn't really affect new that much (except for
    array new---but I've never found a use for that anyway).
    Probably because it wasn't felt that new was broken.

    --
    James Kanze
     
    James Kanze, Nov 20, 2009
    #5
  6. sfuerst

    White Wolf Guest

    Pavel wrote:
    > sfuerst wrote:
    >> Hello, I've written an article at
    >> http://locklessinc.com/articles/10_problems_with_c /
    >> that is unfortunately way too long to post here, detailing ten
    >> perceived problems with C++, together with some possible solutions.
    >> The list kind of looks like the typical one brought up by novices,
    >> complaining about things like exceptions and multiple inheritance.
    >> However, the actual issues discussed tend to be more subtle and low-
    >> level than what you are probably thinking. In particular, none of the
    >> "problems" are complaints about the existence of features, just on
    >> their current syntax, or typical underlying implementation.
    >>
    >> The 10 problems are:
    >> 1) The "new" keyword.
    >> 2) Exceptions
    >> 3) Implementations of Multiple Inheritance
    >> 4) Member Pointers and Member Function Pointers
    >> 5) 0 is NULL
    >> 6) Operator Overloading
    >> 7) Template Syntax
    >> 8) The "export" Keyword
    >> 9) Classes verses Structs
    >> 10) Barriers
    >>
    >> Unfortunately, some of the solutions aren't particularly good. (The
    >> worst one probably is a replacement syntax for the new keyword.)
    >> However, constructive criticism has to start somewhere.
    >>
    >> Any comments, or flames are welcome. :)
    >>
    >> Steven

    > I am surprised you did not complain about the preprocessor. Ugly and
    > powerless. No loops, no procedures, no way to tell a macro from a
    > language keyword or name, no way to even insert a newline into macro
    > expansion. I wonder why they had to re-invent that particular wheel when
    > much superior PL/1 preprocessor had been around since 60s.
    >
    > Maybe if C had a good preprocessor there would be no need for those ugly
    > templates in C++. And then an average-sized program would not take
    > infinity to compile at multi-GHz CPU. And you wouldn't get 9999
    > 9997-character lines of unreadable error messages for missing a const
    > keyword or forgetting to include a header file with yet another overload
    > of << operator. All pipe dreams I guess..
    >
    > I remember how Turbo-C and especially Turbo-Pascal used to compile on
    > 5-MHz CPU and can't help crying :)
    >
    > How's that for a good flame igniter?


    I think you have over done it. :)
     
    White Wolf, Nov 20, 2009
    #6
  7. sfuerst

    Bo Persson Guest

    sfuerst wrote:
    > Hello, I've written an article at
    > http://locklessinc.com/articles/10_problems_with_c / that is
    > unfortunately way too long to post here, detailing ten
    > perceived problems with C++, together with some possible solutions.
    > The list kind of looks like the typical one brought up by novices,
    > complaining about things like exceptions and multiple inheritance.
    > However, the actual issues discussed tend to be more subtle and low-
    > level than what you are probably thinking. In particular, none of
    > the "problems" are complaints about the existence of features, just
    > on
    > their current syntax, or typical underlying implementation.
    >
    > The 10 problems are:
    > 1) The "new" keyword.
    > 2) Exceptions


    Ok, I'll take on number 2. :)

    Constructors is just one reason for exceptions. Overloaded operators
    is another one. How would you return your failed code from an
    operator+()?



    Bo Persson
     
    Bo Persson, Nov 20, 2009
    #7
  8. sfuerst

    Balog Pal Guest

    "sfuerst" <>
    > Hello, I've written an article at
    > http://locklessinc.com/articles/10_problems_with_c /
    > that is unfortunately way too long to post here, detailing ten
    > perceived problems with C++, together with some possible solutions.


    Sorry to spoil the day, but the think reads like a collection of rants
    coming from half-educated people collected; and the "possible solutions" are
    certainly not there.

    I stay with real work made in the field, like

    Matthew Wilson
    Imperfect C++: Practical Solutions for Real-Life Programming (Paperback)
    http://www.amazon.com/Imperfect-Practical-Solutions-Real-Life-Programming/dp/0321228774

    I suggest you read it, and discover stuff including the area you tried to
    cover...

    > The list kind of looks like the typical one brought up by novices,
    > complaining about things like exceptions and multiple inheritance.
    > However, the actual issues discussed tend to be more subtle and low-
    > level than what you are probably thinking.


    Indeed :) The road goes pretty far.
     
    Balog Pal, Nov 20, 2009
    #8
  9. sfuerst

    sfuerst Guest

    On Nov 19, 4:52 pm, "Alf P. Steinbach" <> wrote:
    > * sfuerst:
    >
    > > Hello, I've written an article athttp://locklessinc.com/articles/10_problems_with_c++/
    > > that is unfortunately way too long to post here, detailing ten
    > > perceived problems with C++, together with some possible solutions.
    > > The list kind of looks like the typical one brought up by novices,

    >
    > He he, it certainly does. :)
    >
    > But kudos (speling?) to you for writing it up.
    >
    > For that can both help you and help many others.
    >
    > > complaining about things like exceptions and multiple inheritance.
    > > However, the actual issues discussed tend to be more subtle and low-
    > > level than what you are probably thinking.  In particular, none of the
    > > "problems" are complaints about the existence of features, just on
    > > their current syntax, or typical underlying implementation.

    >
    > > The 10 problems are:
    > > 1) The "new" keyword.

    >
    > OK, there's much wrong.
    >
    > First, "Unfortunately, the new keyword doesn't allow [...] an override." is
    > wrong. You override the allocation aspect by defining operator new (and/or
    > operator new[], which is the allocation function, which can be overridden per
    > class as well as overriding the global default (where, to boot, you can override
    > the action taken on allocation failure via set_new_handler). And you can
    > "override" the initialization action by defining suitable constructors.


    I think you've missed the point. In other languages, people are able
    to globally override memory allocation. This is done for debugging:
    To find a memory leak, you can store the file and line of the
    allocation call, and see where the allocations that are never freed
    come from. Another use is profiling: What sized allocations are your
    program repeatedly allocating and freeing? Perhaps the use of some
    other allocator other than the default could improve performance.

    With C++, you can use the placement new syntax to pass extra
    information to an overridden new routine. The problem is that there
    is no way to globally cause this to happen, without manually editing
    every single call to new in your program. (You can override
    individual classes, no problem... but the only available global
    overrides are operator new(size_t) and operator new[](size_t), and
    these don't let you access the file and line number you need.)

    If new was some sort of operator instead of a keyword, and used
    brackets to surround the type, then it would be possible to use a
    macro to do this. Unfortunately, this isn't the case.

    i.e We'd like to do something like:
    #ifdef DEBUG_ALLOCATIONS
    #define new(T) new(T, __FILE__, __line__)
    #endif

    Imagine if new was a template... (convert it from a keyword into
    something within the standard library),
    and then imagine if templates used normal brackets instead of greater
    than and less than signs. These "tiny" changes increase the
    orthogonality enough that the above becomes possible. Unfortunately,
    macros require normal brackets, which is why both changes are
    required, rather than just the first.

    > Second, this is wrong: "A second problem with the new keyword is that it
    > combines two different operations in one. The first is to allocate memory, the
    > second is to initialize it. This combination means that initializing an array is
    > impossible to do with anything other than the default constructor."
    >
    > 'new' is designed to very strongly couple allocation and initialization, with
    > automatic rollback. It's extremely tricky to do manually, that is, to do it
    > correctly without language support. If C++ didn't have 'new' to do it, it would
    > need some other mechanism to do it, which would then be used instead of 'new'.
    >
    > Also, it's wrong that it's impossible to initialize an array in other ways than
    > using a default constructor.
    >
    > For example,
    >
    >      std::vector<int> a( 42, 999 );


    This isn't an array. This is a vector, but I think you know that.
    You don't use delete[] with a vector... (Unless you have an array of
    vectors. :p )
    Of course, I know this is just a nice way of saying that most people
    shouldn't use raw arrays. They are out of date, and vectors should be
    used instead. If so, this actually makes the insane non-compatible
    change easier. The only code that would need to change is that within
    the definition of vector<> itself, which is most likely using arrays
    internally for performance reasons.

    > Third, this is wrong: "Similarly, destructing an array with the delete[]
    > operator is inefficient.". delete[] is designed for maximal efficiency. The
    > trade-offs made to achieve that efficiency, in particular that the programmer
    > must supply the knowledge of whether it's delete or delete[] (just in order to
    > save a byte or two of memory!) is a problem, but the efficiency is not. :)


    The problem with delete[] is that it exists. You use "delete" with
    everything else. Why should arrays be special? Special cases are the
    very definition of non-orthogonality.

    The basic argument is that if you have an array, you probably know its
    size. (vector<> certainly does.) If you don't know its size, then
    your code probably has a latent buffer overflow problem, and is highly
    likely to be buggy elsewhere. Therefore, there should be no problem
    passing that size to some deletion routine when you need to
    deconstruct the objects in that array. Of course this would totally
    break backwards compatibility... but the whole point of exploring
    these things is to look at what is possible if we allow that.

    Steven
     
    sfuerst, Nov 20, 2009
    #9
  10. sfuerst

    sfuerst Guest

    On Nov 20, 8:33 am, "Bo Persson" <> wrote:
    > sfuerst wrote:
    > > Hello, I've written an article at
    > >http://locklessinc.com/articles/10_problems_with_c /that is
    > > unfortunately way too long to post here, detailing ten
    > > perceived problems with C++, together with some possible solutions.
    > > The list kind of looks like the typical one brought up by novices,
    > > complaining about things like exceptions and multiple inheritance.
    > > However, the actual issues discussed tend to be more subtle and low-
    > > level than what you are probably thinking.  In particular, none of
    > > the "problems" are complaints about the existence of features, just
    > > on
    > > their current syntax, or typical underlying implementation.

    >
    > > The 10 problems are:
    > > 1) The "new" keyword.
    > > 2) Exceptions

    >
    > Ok, I'll take on number 2.  :)
    >
    > Constructors is just one reason for exceptions. Overloaded operators
    > is another one. How would you return your failed code from an
    > operator+()?
    >
    > Bo Persson


    You are right, basically you are stuck. Exceptions are sometimes the
    only way to communicate failure conditions in some cases. However,
    the problem with exceptions is not that they exist at all... its that
    they provide a poorly documented interface to functions. In theory,
    all functions should list what potential exceptions they could throw
    as part of their definition / external documented interface. In
    practice, this rarely happens. The reason is that far too many
    exceptions are possible in any non-trivial code. The combinatorial
    explosion would lead to the poor programmer having to do much extra
    typing. Thus the argument leads to: we can't get rid of them... but
    can we minimize their use? The answer to that is a probable "yes".
    If their use is minimized, then the extra typing is minimized... and
    enforcing their documentation isn't quite so much of a burden.

    In short, wouldn't it be cool if the compiler could guarantee that
    your code was exception safe? To do so, it simply needs more
    information than what currently is usually provided.
     
    sfuerst, Nov 20, 2009
    #10
  11. sfuerst

    Bo Persson Guest

    sfuerst wrote:
    > On Nov 19, 4:52 pm, "Alf P. Steinbach" <> wrote:
    >
    >> Third, this is wrong: "Similarly, destructing an array with the
    >> delete[] operator is inefficient.". delete[] is designed for
    >> maximal efficiency. The trade-offs made to achieve that
    >> efficiency, in particular that the programmer must supply the
    >> knowledge of whether it's delete or delete[] (just in order to
    >> save a byte or two of memory!) is a problem, but the efficiency is
    >> not. :)

    >
    > The problem with delete[] is that it exists. You use "delete" with
    > everything else. Why should arrays be special? Special cases are
    > the
    > very definition of non-orthogonality.


    Arrays ARE special! We got that from the C language.

    In C++ this is solved by std::vector, which never ever leaks memory.
    What is there left to dbug?


    Bo Persson
     
    Bo Persson, Nov 20, 2009
    #11
  12. sfuerst

    Balog Pal Guest

    "sfuerst" <>
    >>

    I think you've missed the point. In other languages, people are able
    to globally override memory allocation. This is done for debugging:
    To find a memory leak, you can store the file and line of the
    allocation call, and see where the allocations that are never freed
    come from. Another use is profiling: What sized allocations are your
    program repeatedly allocating and freeing? Perhaps the use of some
    other allocator other than the default could improve performance.

    With C++, you can use the placement new syntax to pass extra
    information to an overridden new routine. The problem is that there
    is no way to globally cause this to happen, without manually editing
    every single call to new in your program.
    <<

    TMK there is a bunch of leak detectors out there.
    But I never used any of them -- Visual C++ has it built-in for decades. And
    all it takes a single #define new debug_new at the front of the source. If
    you use it, then you get the source file/line of allocation besides the
    leaked block address, size and content.

    The last time I had to put together a ehap diagnostic was around '94, even
    then I was possibly just not aware of a ready solution...

    Manually editing lines of code?

    What you ask for, is sitteng there, working, discover how it is done instead
    of claiming it impossible.

    OTOH, the real way to make correct code is definitely not going by that info
    but through using consistent RAII-like handling, and reviews enforcing it.

    As test runs will hardly cover all possible paths including errors and
    exceptions, so relying on the empty leak list from a random run is nothing
    but illusion of being okay. While with trivial style it is easy to make
    leaks impossible.

    Why invest in better patches instead of cure the problem at roots?



    (You can override
    individual classes, no problem... but the only available global
    overrides are operator new(size_t) and operator new[](size_t), and
    these don't let you access the file and line number you need.)

    If new was some sort of operator instead of a keyword, and used
    brackets to surround the type, then it would be possible to use a
    macro to do this. Unfortunately, this isn't the case.

    i.e We'd like to do something like:
    #ifdef DEBUG_ALLOCATIONS
    #define new(T) new(T, __FILE__, __line__)
    #endif

    Imagine if new was a template... (convert it from a keyword into
    something within the standard library),
    and then imagine if templates used normal brackets instead of greater
    than and less than signs. These "tiny" changes increase the
    orthogonality enough that the above becomes possible. Unfortunately,
    macros require normal brackets, which is why both changes are
    required, rather than just the first.

    ....
    >You don't use delete[] with a vector... (Unless you have an array of

    vectors. :p )

    You should not use delete[] at all, ever. Sending all the related problems
    to limbo. (this one is even easy to "review" by grep...)

    >Of course, I know this is just a nice way of saying that most people

    shouldn't use raw arrays. They are out of date, and vectors should be
    used instead.

    vectors, or other fit collections -- they are easy to find ready to use. And
    even writing one is simpler than dealing with the related problems. I'm
    sure there is no use case where built-in array would beat them with one
    dimension. With multi dim see the relevant chapter in Wilson.

    >The problem with delete[] is that it exists.


    So eradicate it for good. How much of real problem is THAT really?

    Especially compared to the can of worms those raw arrays bring, especially
    paired with dynamic allocation...
     
    Balog Pal, Nov 20, 2009
    #12
  13. * sfuerst:
    > On Nov 19, 4:52 pm, "Alf P. Steinbach" <> wrote:
    >> * sfuerst:
    >>
    >>> Hello, I've written an article athttp://locklessinc.com/articles/10_problems_with_c++/
    >>> that is unfortunately way too long to post here, detailing ten
    >>> perceived problems with C++, together with some possible solutions.
    >>> The list kind of looks like the typical one brought up by novices,

    >> He he, it certainly does. :)
    >>
    >> But kudos (speling?) to you for writing it up.
    >>
    >> For that can both help you and help many others.
    >>
    >>> complaining about things like exceptions and multiple inheritance.
    >>> However, the actual issues discussed tend to be more subtle and low-
    >>> level than what you are probably thinking. In particular, none of the
    >>> "problems" are complaints about the existence of features, just on
    >>> their current syntax, or typical underlying implementation.
    >>> The 10 problems are:
    >>> 1) The "new" keyword.

    >> OK, there's much wrong.
    >>
    >> First, "Unfortunately, the new keyword doesn't allow [...] an override." is
    >> wrong. You override the allocation aspect by defining operator new (and/or
    >> operator new[], which is the allocation function, which can be overridden per
    >> class as well as overriding the global default (where, to boot, you can override
    >> the action taken on allocation failure via set_new_handler). And you can
    >> "override" the initialization action by defining suitable constructors.

    >
    > I think you've missed the point. In other languages, people are able
    > to globally override memory allocation. This is done for debugging:
    > To find a memory leak, you can store the file and line of the
    > allocation call, and see where the allocations that are never freed
    > come from. Another use is profiling: What sized allocations are your
    > program repeatedly allocating and freeing? Perhaps the use of some
    > other allocator other than the default could improve performance.
    >
    > With C++, you can use the placement new syntax to pass extra
    > information to an overridden new routine. The problem is that there
    > is no way to globally cause this to happen, without manually editing
    > every single call to new in your program.


    You can just use a macro.

    Check out e.g. Microsoft's MFC.

    Ugh, I never thought I'd direct *anyone* to MFC, but it does this. There was by
    the way an infamous bug related to that macro. They'd originally forgotten to
    define placement delete, thus leaking memory when exceptions occurred in debug
    builds...


    > (You can override
    > individual classes, no problem... but the only available global
    > overrides are operator new(size_t) and operator new[](size_t), and
    > these don't let you access the file and line number you need.)
    >
    > If new was some sort of operator instead of a keyword, and used
    > brackets to surround the type, then it would be possible to use a
    > macro to do this. Unfortunately, this isn't the case.
    >
    > i.e We'd like to do something like:
    > #ifdef DEBUG_ALLOCATIONS
    > #define new(T) new(T, __FILE__, __line__)
    > #endif


    You're homing in on one of the solutions, yes. :)


    [snip]
    >> Also, it's wrong that it's impossible to initialize an array in other ways than
    >> using a default constructor.
    >>
    >> For example,
    >>
    >> std::vector<int> a( 42, 999 );

    >
    > This isn't an array. This is a vector, but I think you know that.
    > You don't use delete[] with a vector... (Unless you have an array of
    > vectors. :p )


    The example just shows that you can construct elements of an array any way you
    wish. There's nothing magical about std::vector. It's just a class that you can
    define yourself.


    [snip]
    >> Third, this is wrong: "Similarly, destructing an array with the delete[]
    >> operator is inefficient.". delete[] is designed for maximal efficiency. The
    >> trade-offs made to achieve that efficiency, in particular that the programmer
    >> must supply the knowledge of whether it's delete or delete[] (just in order to
    >> save a byte or two of memory!) is a problem, but the efficiency is not. :)

    >
    > The problem with delete[] is that it exists. You use "delete" with
    > everything else. Why should arrays be special? Special cases are the
    > very definition of non-orthogonality.


    That's the "byte or two" I mentioned in the quote.


    > The basic argument is that if you have an array, you probably know its
    > size. (vector<> certainly does.) If you don't know its size, then
    > your code probably has a latent buffer overflow problem, and is highly
    > likely to be buggy elsewhere. Therefore, there should be no problem
    > passing that size to some deletion routine when you need to
    > deconstruct the objects in that array. Of course this would totally
    > break backwards compatibility... but the whole point of exploring
    > these things is to look at what is possible if we allow that.


    Think about a zero-terminated string, and functions like

    char const* dup( char const* s )
    {
    return strcpy( new char[strlen(s)+1], s );
    }

    That's about "knowing the size", often, as here, you don't even know the size
    specified at allocation, but would have to obtain it by e.g. using strlen.


    Cheers & hth.,

    - Alf
     
    Alf P. Steinbach, Nov 20, 2009
    #13
  14. sfuerst

    dragan Guest

    "Bo Persson" <> wrote in message
    news:...
    > sfuerst wrote:
    >> Hello, I've written an article at
    >> http://locklessinc.com/articles/10_problems_with_c / that is
    >> unfortunately way too long to post here, detailing ten
    >> perceived problems with C++, together with some possible solutions.
    >> The list kind of looks like the typical one brought up by novices,
    >> complaining about things like exceptions and multiple inheritance.
    >> However, the actual issues discussed tend to be more subtle and low-
    >> level than what you are probably thinking. In particular, none of
    >> the "problems" are complaints about the existence of features, just
    >> on
    >> their current syntax, or typical underlying implementation.
    >>
    >> The 10 problems are:
    >> 1) The "new" keyword.
    >> 2) Exceptions

    >
    > Ok, I'll take on number 2. :)
    >
    > Constructors is just one reason for exceptions. Overloaded operators is
    > another one. How would you return your failed code from an operator+()?


    That's the wrong question to ask though because it pre-supposes exceptions.
    The question is, "what are the alternatives?".

    1. Don't write code that errors in constructors or operators.
    2. Do default error handling instead of requiring propogation via
    exceptions: exit(), perhaps.
    3. Use another error handling technique.
    4. ?

    The argument for exceptions goes something like this: Some people want to
    write code where errors can happen in constructors and operators, therefore
    exceptions were created. Because exceptions were created, why not just go
    ahead and use them all over the place.

    It's a classic case of the exceptional case (no pun intended, but a little
    humourous anyway) botching up the common case.
     
    dragan, Nov 21, 2009
    #14
  15. sfuerst

    dragan Guest

    "sfuerst" <> wrote in message
    news:...
    > Hello, I've written an article at
    > http://locklessinc.com/articles/10_problems_with_c /
    > that is unfortunately way too long to post here, detailing ten
    > perceived problems with C++, together with some possible solutions.


    From the article:

    "With explicit construction, the zero-argument count, and no-return-value
    requirements for a constructor evaporate."

    What about compiler-generated temporaries created via a constructor? You
    pre-supposed only one pattern of construction: that in which the developer
    is writing code. There is not just one pattern of construction to address.
     
    dragan, Nov 21, 2009
    #15
  16. sfuerst

    dragan Guest

    "sfuerst" <> wrote in message
    news:...
    > Hello, I've written an article at
    > http://locklessinc.com/articles/10_problems_with_c /
    > that is unfortunately way too long to post here, detailing ten
    > perceived problems with C++, together with some possible solutions.


    From the article:

    "As currently implemented, the export keyword cannot speed up compile time.
    The repeated work that we try so hard to remove is simply deferred until
    link time. This is a disaster, and removes the entire point of having this
    feature."


    I thought the gist of "export" was to give the ability to hide template
    implementation source code. I never thought it's purpose was at all tied to
    performance.
     
    dragan, Nov 21, 2009
    #16
  17. sfuerst

    dragan Guest

    "sfuerst" <> wrote in message
    news:...
    > Hello, I've written an article at
    > http://locklessinc.com/articles/10_problems_with_c /
    > that is unfortunately way too long to post here, detailing ten
    > perceived problems with C++, together with some possible solutions.


    In the section titled "Implementation of Multiple Inheritence", you just
    regurgitated well-known information that can be found in textbooks. The
    solution to multiple inheritence is to not do it or only allow a restricted
    form of it. Then all that thunking and offsetting simply goes away.
     
    dragan, Nov 21, 2009
    #17
  18. sfuerst

    dragan Guest

    "sfuerst" <> wrote in message
    news:...
    > Hello, I've written an article at
    > http://locklessinc.com/articles/10_problems_with_c /
    > that is unfortunately way too long to post here, detailing ten
    > perceived problems with C++, together with some possible solutions.


    From the article: "Why not use this difference between plain-old-data and
    more complex objects to define the difference between structs and classes?"

    Bjarne and his peers wrestled with that (and probably argued about it a lot
    too) when C++ was first designed. Bjarne notes in his book "The Design and
    Evolution of C++" (which you should read or read again because you seem to
    be oblivious to what was written in that tome) that he thought if he would
    have created such a distinction (that is, ANY significant distinction)
    between structs and classes that C++ would have been "stillborn". We'll
    never know what would have been had structs and classes been fundamentally
    different, but the reason why structs and classes are defined as they are is
    well-documented.
     
    dragan, Nov 21, 2009
    #18
  19. sfuerst

    dragan Guest

    "sfuerst" <> wrote in message
    news:...
    > Hello, I've written an article at
    > http://locklessinc.com/articles/10_problems_with_c /
    > that is unfortunately way too long to post here, detailing ten
    > perceived problems with C++, together with some possible solutions.


    Passages from the article are enclosed in quotation marks below).

    "So the C++ language has quite a few problems."

    You say that so matter-of-factly and as if you were trying to persuade
    others, perhaps "novices" that the C++ designers "missed something" or
    didn't think it over enough before making their design choices or that they
    were wrong choices. While a tiny bit of that surely exists, C++ is what it
    is for consideration of the "bigger-picture" in which it exists, rather than
    in comparison of an apple to an orange. A lot of the "baggage" that C++
    carries is BY DESIGN: mostly for C compatibility and compatibility with
    legacy C++ code.

    "However, they all seem fixable if one were willing to break source and ABI
    backwards compatibility."

    That would be not in the spirit of C++ and would be instead a new language.
    The language D has that charter, I believe. You may want to check it out.

    "Hopefully, this has provided constructive criticism, and enough detail in
    the solutions proposed to be useful."

    While some low-level details you spoke about in your article are news to me
    (I program at a much higher level but find information about the
    underpinnings an interesting hobby), I highly doubt that in the larger scope
    of this newsgroup that you've noted anything that hasn't been analysed a
    thousand times before by thousands of other developers and that the C++
    committee members don't discuss on a daily basis. (No offense meant).
     
    dragan, Nov 21, 2009
    #19
  20. sfuerst

    dragan Guest

    "Paavo Helde" <> wrote in message
    news:Xns9CCA2007E5AACpaavo256@216.196.109.131...
    > "dragan" <> wrote in
    > news:wEGNm.6704$:
    >


    > You cannot feasible solve error reporting 10 call frames up without
    > exceptions, possibly through different libraries, without turning all the
    > source code into a mess.


    Quite easily actually. An example is the new operator's set_new_handler.

    I don't have privy to those "large applications" that everyone keeps talking
    about, but if I did I'd probably "refactor" them so they wouldn't be so
    unwieldly.

    OTOH, if you are talking about project issues and the larger scope of
    cross-component (by different providers) interoperability, that's a
    different argument. Probably one of a pipe dream though since a C++ eco
    system to that level isn't going to happen except maybe as a niche. I'd be
    interested to hear about some of these large projects that used libraries
    from multiple vendors to build large scale applications and how it went. To
    me, I would think it would be just making an integration mess since coding
    styles with C++ vary so much. And what about duplication? One vendor
    considers the standard string to be less than useful so it creates a
    proprietary one for use specifically for use with it's library, and then the
    next vendor B has quirk X and on and on.
     
    dragan, Nov 21, 2009
    #20
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. David
    Replies:
    4
    Views:
    421
    David
    Nov 29, 2005
  2. Matthew Scott
    Replies:
    0
    Views:
    310
    Matthew Scott
    May 6, 2005
  3. Rotem
    Replies:
    23
    Views:
    643
    Trent Mick
    Sep 15, 2005
  4. Michael Hoffman

    Improvements for import this

    Michael Hoffman, Apr 15, 2006, in forum: Python
    Replies:
    0
    Views:
    241
    Michael Hoffman
    Apr 15, 2006
  5. untitled
    Replies:
    1
    Views:
    346
    Chris Theis
    Mar 3, 2007
Loading...

Share This Page