C and C++

Ö

Öö Tiib

Writing "auto main() -> int" instead of the canonical "int main()" is so
anally retentive and fucktarded that words almost escape me.

Do those things you said mean "so attractive that you want certainly to
participate" in plain English?

I just see 8 characters added with purpose to make clear that it is C++
not C code.
 
J

James Kanze

I think Mr. Kanze and others have talked about giving functions
their own source/implementation files in order to minimize the
size of executables. I sometimes split a function off into a
separate file like that.

The case for fstream is different, because it is a template.
Basically, there are three cases to consider:

-- Non-template non-virtual functions: There is no difference
between C and C++ here. The granularity of the linker (at
least most linkers) is the object file. If you put each of
your functions in a separate source file, then the linker
will pull in exactly what is needed, no more, no less. If
you put all of your functions in one big source file, the
linker will plu in all of your functions. Both in C and in
C+++.

-- Virtual functions: A virtual function is "used" any time the
class is instantiated (since its address will appear in the
vtable). If you instantiate a class of type C, then all of
the virtual functions of class C will be pulled in,
regardless of how you organize your source files.

-- Function templates (and member functions of class
templates): The linker generally has nothing to do with
this. The templates will be instantiated if they are used,
and not otherwise. (And here, again, virtual member
functions are "used" anytime the class itself is
instantiated.)

std::fstream is a class template, so the last point applies. It
does have virtual functions, but one, the destructor, will be
used, forceably, and the only other one, rdbuf, is more or less
trivial.

In fact, in this case, unless the implementation uses fprintf or
sprintf in its implementation, the C++ model should result in
far less code being pulled in. If you use printf, for example,
you will pull in all of the code for floating point formatting,
even if your program doesn't have a single floating point value
in it. (Older readers may remember that early implementations
of C generally had two implementations of the library, one with
floating point support, and one without. Because the floating
point support did take up a lot of space, and without virtual
memory and with only 64KB of memory, that space was important.)
 
J

James Kanze

[...]
Perhaps it was the assertion that moving on to a more
advanced/complex language without understanding the basics will not
prove fruitful?

From the users point of view, C++ is a simpler, less complex
language than C, because it automatically takes care of some of
the more complex issues (like string handling and arrays that
actually work) for you. There *are* a number of unnecessary
complications, but most of the ones which actually cause
practical problems when programming (like double silently
converting to an int) are inherited from C.

[...]
Enlighten me please. Which standard headers result in code being
generated?

<iostream>. "The results of including <iostream> in
a translation unit shall be as if <iostream> defined an instance
of ios_base::Init with static storage duration." ios_base::Init
has a trivial constructor and destructor, and the compiler must
generate code to ensure that they are called.

Of course, there will usually be only one or two sources which
He said including the header fstream adds overhead to a program. If
it does, I'd like to learn how.

<fstream> is safe.

It's rare that code size due to IO is a problem, but compared to
C, C++ should require less library code (supposing the library
is written intelligently), but there will be more code at the
client side: "fprintf( f, "%d\n", i )" pulls in all of the
output formatting code, including that for floating point, but
at the call site, it is a single function with three arguments;
"f << i << std::endl" only pulls in the code for formatting
integers, but will result in two function calls at the call
site, each one with two arguments.

Of course, if someone later changes i to type long, the
C version suddenly ends up with undefined behavior, where as the
C++ version just goes one working correctly. But since no one
ever has to maintain a program, who cares.
 
J

James Kanze

Writing "auto main() -> int" instead of the canonical "int main()" is so
anally retentive and fucktarded that words almost escape me.

Now, now. Some people like obfuscation, or change just for
changes sake. Or maybe he's paid by the character: the above
replaces a very clear 10 character sequence with an
18 character sequence which isn't quite as clear, at least for
current C++ programmers.
 
J

James Kanze


That's a good article, but it misses the most important point:
in C, you define a struct and a number of functions to
manipulate it, and you cross your fingers that no one accesses
any of the members except through your functions (or you only
provide a forward declaration of the struct, and add a factory
function, and require all instances to be dynamically
allocated); in C++, you make the data private, the functions
members, and if the struct itself needs dynamic memory (or any
other resources), you add a constructor and a destructor. In
fact, you probably add a constructor regardless, to ensure that
no one accidentally uses the date before it it is initialized.

This simple difference means that any time more than one
programmer is working on the code, or the code must be
maintained for more that six months, C++ is a better choice.
Even if you don't need polymorphism or templates or operator
overloading or function overloading.

This simple difference also means that from a practical point of
view, using C++ will result in shorter time to market, and less
total cost over the program lifetime. (Of course, the
additional features can in many cases reduce time to market and
total costs even more.)
 
J

James Kanze

On 01/11/2013 15:51, Paul ( The Troll ) wrote:
One shouldn't use printf in a C++ program. printf is not type safe.

And it's not extensible. And you can't add output for user defined
types. And you can't add new targets (and you need a differently
named function just to get a string). And you can't add new
formatting options for your own types.

The printf family is hardly usable.
 
A

Alf P. Steinbach

Now, now. Some people like obfuscation, or change just for
changes sake. Or maybe he's paid by the character: the above
replaces a very clear 10 character sequence with an
18 character sequence which isn't quite as clear, at least for
current C++ programmers.

You could just ask, you now.

There is of course a good rationale. I do not do things willy-nilly.


Cheers & hth.,

- Alf
 
C

Cholo Lennon

You could just ask, you now.

There is of course a good rationale. I do not do things willy-nilly.

Please, where/which is the rationale? Who wrote it? IMHO this is not the
best case to use the trailing return syntax. C'mon, it's the well known
function main, why change its shape?

Best regards
 
W

woodbrian77

On Tuesday, November 5, 2013 12:03:26 PM UTC-6, Leigh Johnston wrote:

Please don't swear here.
 
S

Seungbeom Kim


That's a good article, but it misses the most important point:
[..] in C++, you make the data private

Information hiding is certainly a good thing, but I'm not sure if it's
the most important advantage of C++ over C, though opinions may vary,
of course. Especially when many other languages, including C and other
scripting languages, rely on conventions (e.g. "A name that begins with
an underscore is private.") and it doesn't seem like a major source of
problems. Of course you can break it if you really intend to, but more
or less the same thing can be said of C++ as well. And violations are
easy to spot. On the other hand, things like RAII, exceptions, or
generics are much harder to get right by hand.
 
W

woodbrian77

Information hiding is certainly a good thing, but I'm not sure if it's
the most important advantage of C++ over C, though opinions may vary,
of course. Especially when many other languages, including C and other
scripting languages, rely on conventions (e.g. "A name that begins with
an underscore is private.") and it doesn't seem like a major source of
problems. Of course you can break it if you really intend to, but more
or less the same thing can be said of C++ as well. And violations are
easy to spot. On the other hand, things like RAII, exceptions, or
generics are much harder to get right by hand.

I'm sympathetic to this view.
 
I

Ian Collins

Drew said:
Pick a feature, almost any feature, of C++, and there are knowledgeable
posters who will claim that it is essential to the language and
other knowledgeable posters who will claim that it is an unimportant
curiosity.

RAII is an "I have seen the light" religion for some and a really
cool convenience for others.

It is also the only C++ feature that can't be replicated in C. So you
could argue that RAII alone is enough of a reason to use C++ in place of C.
 
N

nick.keighley.zczc

That's a good article, but it misses the most important point:
[..] in C++, you make the data private

Information hiding is certainly a good thing, but I'm not sure if it's
the most important advantage of C++ over C, though opinions may vary,
of course. Especially when many other languages, including C and other
scripting languages, rely on conventions (e.g. "A name that begins with
an underscore is private.")

that would be a bad convention in C as it encroaches on the reserved namespace.
and it doesn't seem like a major source of
problems.

I tend to agree
Of course you can break it if you really intend to, but more
or less the same thing can be said of C++ as well. And violations are
easy to spot. On the other hand, things like RAII, exceptions, or
generics are much harder to get right by hand.

even inheritance is nasty by hand
 
Ö

Öö Tiib

It is also the only C++ feature that can't be replicated in C. So you
could argue that RAII alone is enough of a reason to use C++ in place of C.

C does not have exceptions so it is slightly less important. Also some C
compilers have extensions that let one to RAII (like gcc).

Painful is it however in languages that massively use exceptions but do
not have RAII (like C# or Java).
 
J

James Kanze

In C there's a kludge around that problem, and it's to use, basically,
the Pimpl idiom using an opaque pointer.

I mentionned that later (in a parentheses).
The two biggest problems with
this are, of course, that the program becomes automatically more
error-prone (because it becomes easier to make mistakes and have leaks,
double frees, or accessing freed memory), and the program becomes less
efficient because every instance of that struct needs to be allocated
dynamically (which, as we know, is a really heavy operation.)

You can limit (but not completely eliminate) the runtime impact
by using memory pools. The real issue is the programming one:
we all know how error prone manual memory management can be.
 
Ö

Öö Tiib

Interesting idea. Here's how we did exactly that in the late 70's/early 80's
on one of Burroughs SMP mainframes (built right into the instruction set):

http://vseries.lurndal.org/doku.php?id=instructions:lok

Note particularly the "lock number" field in the 20-digit (10-byte)
lock structure.

The lock instructions provided a standard mutex. The event instructions
provided a standard condition variable.

Hmm. It is easy to imagine how such total order works. What is perhaps
difficult is how to achieve such total order in dynamic world of modern software. Will there be several different mutexes of same level?
 
D

Dombo

Op 08-Nov-13 13:12, Öö Tiib schreef:
C does not have exceptions so it is slightly less important. Also some C
compilers have extensions that let one to RAII (like gcc).

Painful is it however in languages that massively use exceptions but do
not have RAII (like C# or Java).

My experience is that the lack of RAII is not all that painful in these
languages. I don't think it makes sense to consider language features in
isolation. I've been programming C++ for 20 years now, and consider RAII
to be an essential part of the C++ language. Recently I've done a couple
of C# projects and I have a little experience with Java too. Java and C#
have language features, such as garbage collection and the finally
clause, that make the lack of support for RAII less painful and
occasionally these language features are actually more convenient than
RAII. In case of C# you have also the using/IDisposable construct, which
isn't as nice as RAII, but in many cases it is close enough.

Often I see people when confronted with a new programming language
insisting on using the idioms of the programming language they know/like
best. My experience is that that is a recipe for a lot of frustration
and eventually disaster. If you want to program like in Java then use
Java, if you want to program like in C++ then use C++. If you are
picking up a new programming language be sure you pick up also the
idioms that go with that language. If you are not willing to adapt your
programming style then stick to the language for which that style is
appropriate.
 
Ö

Öö Tiib

Op 08-Nov-13 13:12, Öö Tiib schreef:

My experience is that the lack of RAII is not all that painful in these
languages. I don't think it makes sense to consider language features in
isolation. I've been programming C++ for 20 years now, and consider RAII
to be an essential part of the C++ language. Recently I've done a couple
of C# projects and I have a little experience with Java too. Java and C#
have language features, such as garbage collection and the finally
clause, that make the lack of support for RAII less painful and
occasionally these language features are actually more convenient than
RAII.

May be. More verbose code is inconvenient for me but it may be is somehow
more convenient to others.
In case of C# you have also the using/IDisposable construct, which
isn't as nice as RAII, but in many cases it is close enough.

Yes that was exactly what I said. The idioms that replace RAII (chains of catches everywhere, finalizers and disposers) are painful to use for
managing precious resources. The information that some object "manages"
precious resources leaks outside and so the object has to be "managed"
differently by using code. No true encapsulation possible. How to
OOP then?
 
Ö

Öö Tiib

I an nor so sure I would call that an information "leak", in a language
without the ability to tell the compiler to automatically call an
objects destructor, I wouldn't call listing a requirement that the
object needs its "close" function called before the object goes away an
encapsulation "leakage", it is just part of the objects interface.

I was more about leaking that "interfacial property" up the whole cascade. Usage of such class as member turns usually the composite also into "must
close" kind.
It
does say that when designing said interface, the designer needs to think
if there is now, or in some point in the future a possible need for such
an routine, and if so provide it and "require" its call.

Yes. May be we need to manage a member that manages a member that may be
has a file open or network connection or something like that? Everything
"may happen" (perhaps besides bare bone strings and numbers) and so
everything may need manual life-time management. Dealt with it once and
the RAII of C++ feels suddenly so sweet a feature. ;)
If anything, it
is the objects that do NOT require a "close" call that have leaked
implementation details, as if the future that changes, you need to
review all usage of that class.

Ok but with mandatory manual life time management of most things
.... what is the major benefit above idiomatic OOP of C?:

#include <Thing.h>

int main()
{
Thing* thing = Thing_open(42);
if (thing == NULL)
perror("Error opening Thing");
else
{
Thing_trick1(thing);
Thing_trick2(thing);
Thing_close(thing);
}
return 0;
}
Yes, the automatic calling of the "close" function simplify a lot of
code, but some of the critics of C++ also point out that this
automatisity is also a big problem as it can hide significant amounts
of operations.

I just do not buy that argument. The idea of encapsulation is to
establish some borderline. If a class does travel to Moon and back to
fulfill some responsibility of it despite it does not have to then it
is crappy implementation. If it is clear that it has to travel to Moon
and back however then more verbose interface does not aid us any.
We need that done and so someone has to visit Moon.
 
I

Ian Collins

Richard said:
I an nor so sure I would call that an information "leak", in a language
without the ability to tell the compiler to automatically call an
objects destructor, I wouldn't call listing a requirement that the
object needs its "close" function called before the object goes away an
encapsulation "leakage", it is just part of the objects interface. It
does say that when designing said interface, the designer needs to think
if there is now, or in some point in the future a possible need for such
an routine, and if so provide it and "require" its call.

So the design of the interface forces the responsibility for cleaning up
the object onto the consumer. This is no different from C or using raw
resources.
If anything, it
is the objects that do NOT require a "close" call that have leaked
implementation details, as if the future that changes, you need to
review all usage of that class.

Eh? If the managed resource not longer needs cleaning up and you are
using RAII, only the owning object has to be updated.
Yes, the automatic calling of the "close" function simplify a lot of
code, but some of the critics of C++ also point out that this
automatisity is also a big problem as it can hide significant amounts of
operations.

s/operations/opportunities for error/ :)
 

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

Forum statistics

Threads
473,768
Messages
2,569,575
Members
45,052
Latest member
KetoBeez

Latest Threads

Top