A few questions on C++

D

D. Susman

Hi,

1) Should one prefer short / long to int in favour of better
compability? Does the sizeof(int) still vary dramatically between
platforms?

2)Should one check a pointer for NULL before deleting it? Although
deleting a NULL pointer is said to be safe in C++, I see a lot of code
doing the check before deletion. Is this because they still preserve
the C attitude?

3) When is a struct favourable over a class?

4) Should one favor '++iterator' over 'iterator++'? I did some
performance tests myself and did not see a big gap between their
execution times ( by using containers with size 10000000 which contain
objects )

Thanks.
 
V

Victor Bazarov

D. Susman said:
1) Should one prefer short / long to int in favour of better
compability? Does the sizeof(int) still vary dramatically between
platforms?

Dramatically? How much is dramatically? It's still between INT_MAX
and INT_MIN, IIRC. If you need specific sizes, use 'intNN_t' types
soon to be available in a compiler near you (if they aren't yet).

'int' is always "the natural platform size" for numbers, as far as
integer arithmetic is concerned. In most cases it's the fastest way
to perform integer arithmetic (but don't take my word for it, measure
the performance instead of guessing).
2)Should one check a pointer for NULL before deleting it? Although
deleting a NULL pointer is said to be safe in C++, I see a lot of code
doing the check before deletion. Is this because they still preserve
the C attitude?

No need to check. 'delete NULL' is a NOP. No comment on C attitude.
AFAIK 'free(0)' is also a NOP.
3) When is a struct favourable over a class?

When you need compatibility with C.
4) Should one favor '++iterator' over 'iterator++'? I did some
performance tests myself and did not see a big gap between their
execution times ( by using containers with size 10000000 which contain
objects )

It depends. If you don't need the "previous value", use pre-increment.
If you need the previous value _and_ have the iterator increment itself
at the same time, use post-increment.

You did the right thing by measuring the performance. I did the same
thing in our application and came up with _some cases_ where it was
quite apparent that if all else is the same (no need to use the value)
switching to pre-increment would improve speed. You need to ask
yourself: even if the improvement is small, but everything else is the
same, why *not improve* the performance?

V
 
N

Neelesh Bodas

Hi,

1) Should one prefer short / long to int in favour of better
compability? Does the sizeof(int) still vary dramatically between
platforms?

sizeof(int) is implementation-defined and hence no conclusions can be
drawn (rather, it is incorrect to draw any conclusions) regarding
whether it varies across platforms and/or implementations.
2)Should one check a pointer for NULL before deleting it? Although
deleting a NULL pointer is said to be safe in C++, I see a lot of code
doing the check before deletion. Is this because they still preserve
the C attitude?


According to the C++ standard, deleting a NULL pointer is safe. So it
is not mandatory to test the pointer for NULL before deleting it.
However, such a check is certainly necessary if you want to do
something (like calling member function) before doing a delete.
3) When is a struct favourable over a class?

If you have all public members and you want to avoid writing "public"
access specifier in the definition:

struct X
{
int i;
};

is same as

class X
{
public:
int i;
};

4) Should one favor '++iterator' over 'iterator++'? I did some
performance tests myself and did not see a big gap between their
execution times ( by using containers with size 10000000 which contain
objects )
Preincrements are generally faster than postincrements since
postincrements need to make a copy before doing an increment. No such
copy-construction is necessary for pre-increment.


-Neelesh
 
P

Phlip

D. Susman said:
1) Should one prefer short / long to int in favour of better
compability? Does the sizeof(int) still vary dramatically between
platforms?

Use int, and (per a recent thread here) if you are not portable, don't waste
time pretending you are portable. If your boss requests portability,
actually run and test on multiple platforms as you code.

Your question contains the latent assumption that you can never change your
code once its 'int's are installed. If you instead write lots of unit tests,
they will check things like the maximum values for your important numbers,
and they will help you change your variable types when the time comes.

Your remaining int awareness invests in writing tests that check your
program's boundaries.
2)Should one check a pointer for NULL before deleting it?

No, you should use a smart pointer that wraps all such checks up for you.

Next, the line delete(int*)NULL is well-formed and well-defined to do
nothing.

(And note you should use a C++ style cast, in the form
elaborate_cast said:
Although
deleting a NULL pointer is said to be safe in C++, I see a lot of code
doing the check before deletion. Is this because they still preserve
the C attitude?

It's because they don't fold duplication up into smart pointers. _That_ is
preserving the C attitude.
3) When is a struct favourable over a class?

When you need a data bucket that is itself private to an outer class.
4) Should one favor '++iterator' over 'iterator++'? I did some
performance tests myself and did not see a big gap between their
execution times ( by using containers with size 10000000 which contain
objects )

Favor ++it for almost exactly that reason. Specifically, if it is a raw
pointer the pre- and post-increments will be nearly the same speed. But if
you upgrade it into a big object, the it++ form will create a new object,
copy it, and throw it away. The compiler might not be able to optimize this
away.

Now use /el Goog/ and look up "premature optimization". When you learn C++
you should start by learning clean code and good design, and don't worry
about performance until you find a real need.
 
P

Phlip

Neelesh said:
sizeof(int) is implementation-defined and hence no conclusions can be
drawn (rather, it is incorrect to draw any conclusions) regarding
whether it varies across platforms and/or implementations.

Moore's law has brought our platform lineages 16, 24, 32, and now 64 bit
ints. Interpret your advice to mean don't write a program that assumes
sizeof(int) is anything. But, more important, don't write code that needs to
use the sizeof(int). Don't fill your ints up to their maximum too often, and
don't treat the int as binary.
Preincrements are generally faster than postincrements since
postincrements need to make a copy before doing an increment. No such
copy-construction is necessary for pre-increment.

Can't most compilers optimize all that away for simple values?
 
J

Joe Greer

Hi,

1) Should one prefer short / long to int in favour of better
compability? Does the sizeof(int) still vary dramatically between
platforms?

In many ways, the C++ type system is a mess for portability. Most of
the types are specified as minimum sizes, but they can all be bigger
than that. The good news is that universal portability isn't usually a
goal. That is, you usually don't have to write code that will work on
everything from embedded processors through mainframes. So, sometimes
you can make assumptions about the sizes involved in shorts and longs.
int is the native type for the machine and is at least as big as a
short. So, you can portably use it as a fast short.
2)Should one check a pointer for NULL before deleting it? Although
deleting a NULL pointer is said to be safe in C++, I see a lot of code
doing the check before deletion. Is this because they still preserve
the C attitude?

You do not have to check to see if the pointer is NULL before deleting.
This is indeed a holdover from old C days.
3) When is a struct favourable over a class?

The C++ STL seems to use structs for classes with no private members.
Personally, I only use structs for data only structures used with C
apis.
4) Should one favor '++iterator' over 'iterator++'? I did some
performance tests myself and did not see a big gap between their
execution times ( by using containers with size 10000000 which contain
objects )

The rule of thumb is to prefer ++iterator. You mostly see a difference
only when the class implementing ++ is a user defined class. The
reasoning is that there is a certain expense in maintaining the old
value to be returned after incrementing. With types like raw pointers
and scalars, you would be hard pressed to measure a difference, but if
an advantage is available under some conditions, you might as well take
advantage of it idiomatically by always using ++iterator. However,
having said that, it is even more important to follow whatever
conventions the code you are working with is following. No need to have
your code being the only chunks the use ++iterator just to possibly save
a clock cycle.

joe
 
N

Neelesh Bodas

Can't most compilers optimize all that away for simple values?

As I understand it, For PODs (if that is what you mean by 'simple
values'), the pre- or post- increment doesnot make any difference from
the POV of efficiency. But for complex data types, I don't see how
would a compiler optimize away the copy construction.

-N
 
V

Vladislav.Lazarenko

As I understand it, For PODs (if that is what you mean by 'simple
values'), the pre- or post- increment doesnot make any difference from
the POV of efficiency. But for complex data types, I don't see how
would a compiler optimize away the copy construction.

-N

Post-increment always performs copying. So there is always difference.
Sure, you won't see it for integers etc.
Always use pre-increment except situation when you really need pre-
increment. For example:

someContainer.erase(it++);

There is also difference in operator ++ implementation. But it's out
of this topic IMHO.
 
V

Vladislav.Lazarenko

Always use pre-increment except situation when you really need post-
increment.

Sorry for misprint.
 
V

Victor Bazarov

[..]
Always use pre-increment except situation when you really need pre-

I am sure Vladislav meant "always use pre-increment except in
a situation when you really need POST-increment". Just a typo.
increment. For example:

someContainer.erase(it++);

V
 
G

Guest

Hi,

1) Should one prefer short / long to int in favour of better
compability? Does the sizeof(int) still vary dramatically between
platforms?

It depends on how portable you want to be, personally I assume (unless I
have reasons to believe otherwise) that my code will run on hardware
equivalent to a 32-bit x86 (or better) and portability for me is mostly
about making the code compile under multiple OSs.

This means that for me int is usually large enough to contain any number
I might want to use. The exceptions usually involve cases where a
specific number of bits or digits are required, in which case I use the
types from the C header stdint.h.

I cannot see any reason to use short, it is not guaranteed to be of any
specific size so it can be used where such a type is required, and the
extra overhead of using an int is seldom of any consequence. Long might
be useful sometimes when you want to deal with really large numbers, but
then again, I would probably prefer to use a type I know the size of in
those cases.

As for how much sizeof(int) might vary, it depends on the platforms that
you see as potential targets for your code, there are still 8-bit
processors used out there and 64-bit is quite common today, in a few
years you will probably see 128-bit architectures. As I said earlier I
assumes that int will be 32 bits or more for my code, and should I ever
have to port to a platform where that is not true I will worry about
that then, I will not do any extra work for something that might never
happen.
 
V

Vladislav.Lazarenko

I am sure Vladislav meant "always use pre-increment except in
a situation when you really need POST-increment". Just a typo.

Exactly, Victor. Thanks for your correction. I personally consider
people who writes, for example, "for (int i = 0; i < ...; i++)" not
professional developers. Such a bad habit may result in using post-
increment with complex types.
 
P

Puppet_Sock

Moore's law has brought our platform lineages 16, 24, 32, and now 64 bit
ints. Interpret your advice to mean don't write a program that assumes
sizeof(int) is anything. But, more important, don't write code that needs to
use the sizeof(int). Don't fill your ints up to their maximum too often, and
don't treat the int as binary.

In some few rare cases it is necessary to use sizeof(int).
It's not the usual thing, but it's in the language for some
good reasons. Most often you don't need to use it. And by far
the bulk of platform non-specific code won't use it. It would
be my expectation that the vast majority of cases where
sizeof(int) is required are platform specific coding.

As to filling ints to the max value: The thing to do is to
put in appropriate guards against overflows. That is going
to be very specific to the particular application. There's
no particular "too often" involved. It's not something
that is ok as long as you only do it less than some number
of times. You need to specify what acceptable behviour is
regarding integer value ranges, then satisfy the spec.
Just as one example, that might mean restricting the values
on certain parameters so that all the multiplications
performed are restricted to being in range.

I don't know what you mean by "don't treat the int as binary."
Socks
 
V

Victor Bazarov

Exactly, Victor. Thanks for your correction. I personally consider
people who writes, for example, "for (int i = 0; i < ...; i++)" not
professional developers. Such a bad habit may result in using post-
increment with complex types.

Some of us sometimes tend to be a bit harsh on others; we hold them
to our own standards, and if we are perfectionists and expect others
to never make mistakes, it characterises *us* more than it does them.

Using pre-increment after the second semicolon in a 'for' statement
is a good habit to have, but I wouldn't mind seeing post-increment
for built-in types as long as with class instances, like iterators,
and in templates (which are often instantiated for iterators) the
pre-increment form is used. If somebody has the habit of being very
careful with those, no big deal. If, however, there is a wide
spectrum of developers in the team and there is a danger that some
youngster is going to change 'int' to 'iterator' without checking
the increment, I would probably insist on putting the requirement
for the pre-increment into the team/company coding standard. Then
the question of being professional goes away and everybody is happy.

V
 
P

Philip Potter

Victor said:
Dramatically? How much is dramatically? It's still between INT_MAX
and INT_MIN, IIRC. If you need specific sizes, use 'intNN_t' types
soon to be available in a compiler near you (if they aren't yet).

Are these similar to the C99 intNN_t types? As i understand it:

int32_t is guaranteed to be exactly 32 bits wide, 2's complement. It is also
guaranteed to be provided on any platform which already provides an integer type
which fits the bill, but not otherwise.

I wouldn't recommend using C99 intNN_t types unless you knew they were
necessary, because they aren't required to exist on all C99 implementations.

If they're different to the C99 types, why is that? It's not a great idea to
replicate C functionality differently.
 
V

Victor Bazarov

Philip said:
Are these similar to the C99 intNN_t types? As i understand it:

int32_t is guaranteed to be exactly 32 bits wide, 2's complement.

AFAIUI, the "2's complement" part is not the requirement. The actual
representation is implementation-defined.
It
is also guaranteed to be provided on any platform which already
provides an integer type which fits the bill, but not otherwise.

I am not sure about this one. 'long' is required to be at least 32
bits, so if your implementation provides 'long' (as it should to be
a standard C++ compliant implementation), so 'int32_t' would be
typedef'ed to 'long', and provided no matter what. And 'int64_t'
could probably be emulated (using some class). C++ has no limitations
C99 has when type implementation is concerned.
I wouldn't recommend using C99 intNN_t types unless you knew they were
necessary, because they aren't required to exist on all C99
implementations.

We are talking C++ here, not C99.
If they're different to the C99 types, why is that? It's not a great
idea to replicate C functionality differently.

Why not? Worked well for empty structs, the ternary operator...

V
 
P

Phlip

Post-increment always performs copying.

(Not reading the whole thread here but) doesn't return value optimization
apply?

That's what I meant by "simple" objects - not necessarily PODs...
 
T

tragomaskhalos

Hi,

1) Should one prefer short / long to int in favour of better
compability? Does the sizeof(int) still vary dramatically between
platforms?

Years ago I worked on a Windows 3.1 C codebase where short was used
*everywhere* in preference to int; both were 16 bits of course but
the coding standards felt it better to be "explicit" about the size.
The stupidity of this decision was brought home when the code was
ported to a 32 bit Unix environment - I forget the processor type
but when you looked at the machine code produced, everywhere there
was integer (ie short) arithmetic there were all these extra
instructions to mask off the top 16 bits, all utterly futile.

So my guidelines are:
- for general use, use int
- for sizes and offsets, consider size_t (there are pros and cons
here, perhaps an issue for another discussion)
- where a specific number of bits is required, use uint8_t,
uint16_t, uint32_t etc.
 
G

Guest

Years ago I worked on a Windows 3.1 C codebase where short was used
*everywhere* in preference to int; both were 16 bits of course but
the coding standards felt it better to be "explicit" about the size.
The stupidity of this decision was brought home when the code was
ported to a 32 bit Unix environment - I forget the processor type
but when you looked at the machine code produced, everywhere there
was integer (ie short) arithmetic there were all these extra
instructions to mask off the top 16 bits, all utterly futile.

And the irony is that using short does not make the size explicit since
the standard only require short to be at least as large as a signed char
(and not larger than an int).
 

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,769
Messages
2,569,582
Members
45,070
Latest member
BiogenixGummies

Latest Threads

Top