Newbie Question: 'Sizeof' - I'm unclear what it actually measures,Modern equiv of older style refer

J

Juha Nieminen

Christian Hackl said:
It goes against experience because std::vector is used more often than
other containers.

I'm sorry, but I have hard time understanding how "it's more commonly
used" is an argument for std::vector being the correct substitute and
std::deque being the incorrect one. Popularity is not a measurement of
correctness. That's a fallacy.
It goes against common sense because std::deque's
ability of growing in both directions is obviously a special requirement.

The ability of std::vector to grow at all is against "common sense"
because basic arrays can't grow. std::vector adds the capability of
growing the array by adding to the end in constant time, which is
something you can't do out-of-the-box with basic arrays. So that's
something where std::vector already differs from basic arrays.

std::deque additionally gives the possiblity of adding elements to
the beginning in constant time. Why does that make it a "non-array"?
Why is adding to the end ok, but adding to the beginning not?

So no, std::vector doesn't make any more sense than std::deque does.
And of course, you cannot pass a std::deque to a C function usig &d[0]
and d.size(), while you can do this with a std::vector, which only
strengthens the point that vectors are designed as the array replacement
of C++.

I thought you wanted to distance the beginner from such low-level stuff
and teach higher-level constructs instead.
A std::deque has slower element access. How is element access less
important than inserting elements at the beginning?

So using premature optimization as an argument is ok when it makes
std::vector look good, but it's bad when it's used to make basic arrays
look good? You yourself argued that the efficiency arguments for basic
arrays are just "premature optimization". Now you are arguing in favor
of std::vector using the same kind of argument.
Of course, it won't make any difference for a beginner, but again: why
expose him to a special container type instead of simply starting with
the most general and most used, which is std::vector?

What would be wrong in teaching different alternatives and explain their
strengths and weaknesses, and where they are useful and where something
else would be better? A person can learn such things relatively easily,
and claiming otherwise is a bit patronizing, IMO.
 
F

Francesco S. Carta

You mean std::array, from C++0x (or tr1::array, before that).

I just meant any wrapped array that fits. Now I can specify that it
could be either existing or quickly tailored to the needs where
possible, std::array wasn't exactly in my mind when I wrote the above.
Note that any solution involves compromizes. It's far from
trivial to come up with the "correct" solution. (In fact, one
should probably say *a* correct solution, since depending on
what you want, the correct solution might not be the same.)
It took me way more time to come up with the silly test case than to
write the actual wrapper:
//-------
// in some header or hidden in an implementation file
// with fitting explicit instantiations in an appropriate header
// (or maybe exported, if you're lucky)
// this can be, of course, widely extended and improved
template<class T, int SIZE> class Array {
public:
T& operator[](int index) {
return data[index];
}
const T& operator[](int index) const {
return data[index];
}
int size() const {
return SIZE;
}
private:
T data[SIZE];
};

This is interesting. You can't actually instantiate it unless
T has a default constructor, and all of the data are initialized
using the default constructor.

Well, I said it could be improved... I don't know if what you mention
below is achievable with the current standard, though... is it?
Probably the most important single reason for using a C style
array is the aggregate initialization sequence, and the fact
that it can have fully static initialization. (std::array
preserves this quality.)

As I said somewhere else, the upcoming standard is not exactly fully in
my mental toolbox, but what you mention about std::array is definitely
good to know.
 
A

Alf P. Steinbach /Usenet

* Francesco S. Carta, on 25.08.2010 14:48:
You mean std::array, from C++0x (or tr1::array, before that).

I just meant any wrapped array that fits. Now I can specify that it
could be either existing or quickly tailored to the needs where
possible, std::array wasn't exactly in my mind when I wrote the above.
Note that any solution involves compromizes. It's far from
trivial to come up with the "correct" solution. (In fact, one
should probably say *a* correct solution, since depending on
what you want, the correct solution might not be the same.)
It took me way more time to come up with the silly test case than to
write the actual wrapper:
//-------
// in some header or hidden in an implementation file
// with fitting explicit instantiations in an appropriate header
// (or maybe exported, if you're lucky)
// this can be, of course, widely extended and improved
template<class T, int SIZE> class Array {
public:
T& operator[](int index) {
return data[index];
}
const T& operator[](int index) const {
return data[index];
}
int size() const {
return SIZE;
}
private:
T data[SIZE];
};

This is interesting. You can't actually instantiate it unless
T has a default constructor, and all of the data are initialized
using the default constructor.

Well, I said it could be improved... I don't know if what you mention
below is achievable with the current standard, though... is it?
Probably the most important single reason for using a C style
array is the aggregate initialization sequence, and the fact
that it can have fully static initialization. (std::array
preserves this quality.)

As I said somewhere else, the upcoming standard is not exactly fully in
my mental toolbox, but what you mention about std::array is definitely
good to know.

All you have to do support instantiation is to remove the access specifiers.

That turns your class into an aggregate class, which can be initialized by curly
braces syntax in C++98.


Cheers & hth.,

- Alf
 
F

Francesco S. Carta

on said:
* Francesco S. Carta, on 25.08.2010 14:48:
<questions about managing raw arrays>

I wonder why nobody pointed out that we can simply wrap raw arrays into
a template in order to bring along their sizes, and we can do that
quite
easily too.

You mean std::array, from C++0x (or tr1::array, before that).

I just meant any wrapped array that fits. Now I can specify that it
could be either existing or quickly tailored to the needs where
possible, std::array wasn't exactly in my mind when I wrote the above.
Note that any solution involves compromizes. It's far from
trivial to come up with the "correct" solution. (In fact, one
should probably say *a* correct solution, since depending on
what you want, the correct solution might not be the same.)

It took me way more time to come up with the silly test case than to
write the actual wrapper:

//-------
// in some header or hidden in an implementation file
// with fitting explicit instantiations in an appropriate header
// (or maybe exported, if you're lucky)
// this can be, of course, widely extended and improved

template<class T, int SIZE> class Array {
public:
T& operator[](int index) {
return data[index];
}
const T& operator[](int index) const {
return data[index];
}
int size() const {
return SIZE;
}
private:
T data[SIZE];
};

This is interesting. You can't actually instantiate it unless
T has a default constructor, and all of the data are initialized
using the default constructor.

Well, I said it could be improved... I don't know if what you mention
below is achievable with the current standard, though... is it?
Probably the most important single reason for using a C style
array is the aggregate initialization sequence, and the fact
that it can have fully static initialization. (std::array
preserves this quality.)

As I said somewhere else, the upcoming standard is not exactly fully in
my mental toolbox, but what you mention about std::array is definitely
good to know.

All you have to do support instantiation is to remove the access
specifiers.

That turns your class into an aggregate class, which can be initialized
by curly braces syntax in C++98.

So you mean something like this:

//-------

#include <iostream>

template <class T, int SIZE> struct Array {
T data[SIZE];
T& operator[](int index) {
return data[index];
}
const T& operator[](int index) const {
return data[index];
}
int size() const {
return SIZE;
}
};

using namespace std;

int main() {
Array<int, 5> arr = {{1, 2, 3, 4, 5}};
for(int i = 0; i < arr.size(); ++i) {
cout << arr << endl;
}
return 0;
}

//-------

Very good, thanks for your note Alf!
 
J

Juha Nieminen

Christian Hackl said:
At my university, we had a beginner's course in which C++ was taught
like this. char*, arrays and the particularities of unions were
introduced in great detail, and when STL containers were finally
introduced (in less detail than all the other material) the students'
reaction was -- understandably -- along the lines of "what I do I need
all this extra stuff for"? A few years later, when I was a teaching
assistent in a more advanced course, I noticed that many students would
not unlearn those bad habits and were still reluctant to use the
standard library or try Boost components rather than continue to write C
with Classes (which was obviously perceived the "simpler" way of using C++).

The problem is that they started with a low-level construct and taught
is at the main data container, and only much later taught alternatives.

You are proposing, basically, the same thing: Teach std::vector as the
basic construct and then maybe much later basic arrays. Thus the effect
will usually be the same: Students will often be reluctant to use basic
arrays and will always use std::vector, even in situations where it
causes significant performance degradation.

What I was proposing was teaching them *at the same time*, explaining
their properties, advantages and disadvantages, and when one or the other
is better.
 
R

Richard

[Please do not mail me a copy of your followup]

James Kanze <[email protected]> spake the secret code
Still, [C arrays are] for special uses (most of mine are const); for
general work, std::vector is the choice, even if you're not
going to be adjusting the size once it has been constructed.
Agreed.
sizeof() is what you want to tell you the size of a fixed-size
array, i.e. sizeof(array_)/sizeof(array_[0])

For that, I use the template function size (which will cause
a compiler error, rather than a wrong value, if invoked on
a pointer.

Is this your own recipe, or is it in std or boost?
 
A

Alf P. Steinbach /Usenet

* Richard, on 26.08.2010 19:50:
[Please do not mail me a copy of your followup]

James Kanze<[email protected]> spake the secret code
Still, [C arrays are] for special uses (most of mine are const); for
general work, std::vector is the choice, even if you're not
going to be adjusting the size once it has been constructed.
Agreed.
sizeof() is what you want to tell you the size of a fixed-size
array, i.e. sizeof(array_)/sizeof(array_[0])

For that, I use the template function size (which will cause
a compiler error, rather than a wrong value, if invoked on
a pointer.

Is this your own recipe, or is it in std or boost?

It's a set of related functions, and they're not in std or boost.

Not sure but I think first designed by Dietmar Kuhl.

One nice implementation at <url:
http://alfps.wordpress.com/2010/05/10/how-to-avoid-disastrous-integer-wrap-around/>.


Cheers & hth.,

- Alf
 
G

Gennaro Prota

* Richard, on 26.08.2010 19:50:
[Please do not mail me a copy of your followup]

James Kanze<[email protected]> spake the secret code
Still, [C arrays are] for special uses (most of mine are const); for
general work, std::vector is the choice, even if you're not
going to be adjusting the size once it has been constructed.
Agreed.

sizeof() is what you want to tell you the size of a fixed-size
array, i.e. sizeof(array_)/sizeof(array_[0])

For that, I use the template function size (which will cause
a compiler error, rather than a wrong value, if invoked on
a pointer.

Is this your own recipe, or is it in std or boost?

It's a set of related functions, and they're not in std or boost.

Not sure but I think first designed by Dietmar Kuhl.

I think I learned it from some of his code, too. IIRC that was
around 1999 (big caveat: I don't have a good memory :)) and it
was the version that allows getting a compile-time constant
(returning a reference to an array, and to be used in
conjunction with sizeof --and never defined).

In my code, I decided to give up on the constant expression
requirement:

<http://breeze.svn.sourceforge.net/viewvc/breeze/trunk/breeze/counting/>

and I know that James does the same. Of course in C++0x you
could add a constexpr.

At a point, I even wrote a version that gives a constant
expression and also works for multi-dimensional arrays (gives
the count of any projection). And I even managed to make it work
with VC++6 :) But, of course, there's a difference between
experiments and production code (something that Boost should
definitely learn).
 
J

James Kanze

James Kanze <[email protected]> spake the secret code
<[email protected]>
thusly:

[...]
sizeof() is what you want to tell you the size of a fixed-size
array, i.e. sizeof(array_)/sizeof(array_[0])
For that, I use the template function size (which will cause
a compiler error, rather than a wrong value, if invoked on
a pointer.

Is this your own recipe, or is it in std or boost?

It's not my own recipe, since I'd heard about it long before I
actually started using it. I forget who I heard it from,
however, but the idea has been floating around a long time.
 

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,731
Messages
2,569,432
Members
44,832
Latest member
GlennSmall

Latest Threads

Top