Two C++ questions

A

Andre Kostur

Julie said:
John said:
No, not _classes_, I'd never erase a _class_ with memset. But
Julie suggested you can't use mem*() on _anything_ created with
new. Is this really the case that doing something like

int *p=new int[1000000];
memset(p,0,sizeof(int)*1000000);

is a bad idea just because p was allocated with new?

- J.

No, Julie was mistaken.

john

I'd like to see something from the standard that explicitly states
that POD types allocated by new can be manipulated w/ mem* functions.

How about a struct of PODs, what is the 'rule' in that case.

Regardless of what the answer is, I'd say that this is a definite case
of 'bad style'. If you are going to use mem* functions, allocate the
memory w/ malloc and friends.

Um, section 3.9.3 talks about POD types being memcpyable.... (and it
makes no distinction on _where_ the pointer came from, only that they
exist and are valid....)
 
T

tom_usenet

This just stinks of bad design.

If you are going to use mem* functions, allocate the memory w/ malloc.

Why? malloc and new do much the same thing for POD types (although I'm
not suggesting you mix them!). And what's wrong with ::eek:perator new?
What if you want to use a custom global version of new?
If you are going to use the std functions, allocate the memory w/ new.

What, std functions like std::memset?

Tom
 
C

Claudio Puviani

Julie said:
This just stinks of bad design.

It has nothing to do with design. It's an implementation detail.
If you are going to use mem* functions, allocate the memory w/ malloc.

There's no need whatsoever in C++ to use malloc/free, except to support legacy
code. new/delete should be used.
If you are going to use the std functions, allocate the memory w/ new.

The two concepts are COMPLETELY unrelated. There is nothing practical or
theoretical that correlates how and where memory is allocated with the way it
should be manipulated. It's very important for you to make a clear distinction
in your mind about that because if you don't, you'll stub your toes when you
start dealing with more advanced forms of memory management.

Whether you have a block of memory that's allocated on the heap, in free store,
on the stack, or in static space, that block of memory can be manipulated
equally well with mem* functions, standard algorithms, or plain old pointers.
In fact, if you need to copy rad bytes across storage classes, you don't have a
choice but to violate your arbitrary rule:

static char inStatic[100];

void func()
{
char onStack[100];
char *withNew = new char[100];
char *withMalloc = (char *)malloc(100); // deprecated

memcpy(onStack, withNew, 100); // perfectly valid
std::copy(withNew, withNew+100, onStack); // equally valid

memcpy(onStack, inStatic, 100); // perfectly valid
std::copy(inStatic, inStatic+100, onStack); // equally valid

memcpy(onStack, withMalloc, 100); // perfectly valid
std::copy(withMalloc, withMalloc+100, onStack); // equally valid

memcpy(withNew, withMalloc, 100); // perfectly valid
std::copy(withMalloc, withMalloc+100, withNew); // equally valid

// and so on
}

I can't stress this enough: memory allocation and operations on allocated
memory are orthogonal. That's why C++ decouples allocation/deallocation from
object construction/destruction.

Claudio Puviani
 
J

John Harrison

Andre Kostur said:
Julie said:
John said:
No, not _classes_, I'd never erase a _class_ with memset. But
Julie suggested you can't use mem*() on _anything_ created with
new. Is this really the case that doing something like

int *p=new int[1000000];
memset(p,0,sizeof(int)*1000000);

is a bad idea just because p was allocated with new?

- J.

No, Julie was mistaken.

john

I'd like to see something from the standard that explicitly states
that POD types allocated by new can be manipulated w/ mem* functions.

How about a struct of PODs, what is the 'rule' in that case.

Regardless of what the answer is, I'd say that this is a definite case
of 'bad style'. If you are going to use mem* functions, allocate the
memory w/ malloc and friends.

Um, section 3.9.3 talks about POD types being memcpyable.... (and it
makes no distinction on _where_ the pointer came from, only that they
exist and are valid....)

And footnote 37 says that the intent of POD types is that they are
compatible with C.

I don't think this question of how the object is allocate is an issue, if
memset is usable on POD types and not usable on non-POD types it going to be
so regardless of how that type was allocated.

john
 
J

Julie

Claudio said:
The two concepts are COMPLETELY unrelated. There is nothing practical or
theoretical that correlates how and where memory is allocated with the way it
should be manipulated.

You don't allocate memory w/ new, you allocate space for instances of objects,
be they classes or POD types.

malloc is the only way to allocate 'memory'.

mem* functions are for manipulating memory.
 
J

Julie

Claudio said:
There's no need whatsoever in C++ to use malloc/free, except to support legacy
code. new/delete should be used.

Explain to me how you reallocate a block to a smaller size using new w/o
copying?

I would have contemplated adding the following to the C++ language to
accommodate the allocation of (uninitialized) raw blocks of memory:

void * p = new void[size_in_bytes];

Then it would be possible to make the very real distinction between memory and
instance allocation.
 
C

Claudio Puviani

Julie said:
You don't allocate memory w/ new, you allocate space for instances of objects,
be they classes or POD types.

malloc is the only way to allocate 'memory'.

mem* functions are for manipulating memory.

You seriously need to hit the books again. Comments like these will make you
lose any credibility you may have had in this newsgroup.
I would have contemplated adding the following to the C++ language to
accommodate the allocation of (uninitialized) raw blocks of memory:

void * p = new void[size_in_bytes];

Then it would be possible to make the very real distinction between memory and
instance allocation.

C++ simply requires that you phrase it differently:

void * p = new char[size_in_bytes];

If you honestly believe that 'p' doesn't point to memory after this operation,
it's hopeless.

Claudio Puviani
 
J

Jeff Schwab

Julie said:
You don't allocate memory w/ new, you allocate space for instances of objects,
be they classes or POD types.

malloc is the only way to allocate 'memory'.

mem* functions are for manipulating memory.

What do you think "space" means in this context? How does it differ
from "memory?"
 
J

Julie

Claudio said:
You seriously need to hit the books again. Comments like these will make you
lose any credibility you may have had in this newsgroup.

You are absolutely right, I do need to continue studying C++ and programming
topics in general -- I'll *never* get to the point that I can say that I'm
done.

Aside from that, credibility in this forum has little to no value w/ me, so
I'll continue to make comments as I see them, be they right or wrong. I have
no problem being wrong, often am, and learn from each and every thread that I'm
involved in.

My statements reflect my treatment of the disparate allocation schemes.
Perhaps I should have phrased it as "I get in less trouble if I consider new as
an allocator of objects, and malloc as an allocator of raw memory".

Personally, I have very little use for malloc, and as you point out, typically
use it for legacy systems or where/when I'm interfacing w/ the operating system
where raw memory is required. I realize that new char[n] allocates memory, and
that no constructor is called for POD types, but I just find it more confusing
to have separate behaviors for new depending on whether or not the allocation
is for a POD type or a non-POD type. I feel sorry for new learners that have
to learn about the different allocation schemes, as well as learn about the
differences between the special class types.
I would have contemplated adding the following to the C++ language to
accommodate the allocation of (uninitialized) raw blocks of memory:

void * p = new void[size_in_bytes];

Then it would be possible to make the very real distinction between memory and
instance allocation.

C++ simply requires that you phrase it differently:

Right -- but it isn't at all clear what is really intended -- is it intended
that you are allocating space for a block of characters -- or -- are you
allocating a block of raw memory for some (non-char) specific purpose? Using
new char[], you can't determine that w/o careful examination of the context and
comments.

If there were a new void[] construct, it would be be infinitely more clear.
Leave new char[] for allocating space for characters, new void[] for allocating
raw memory. Best part is that there are no *new* keywords, the requirement for
casting the new char[] is eliminated, etc.
void * p = new char[size_in_bytes];

If you honestly believe that 'p' doesn't point to memory after this operation,
it's hopeless.

Of course I *know* that p points to allocated memory, but conceptually (for me)
it is more than just raw bytes, it is allocated space for characters. Using it
for something else (such as raw memory) just seems to break the special
distinction that new implies for allocation.
 
J

Julie

Jeff said:
What do you think "space" means in this context? How does it differ
from "memory?"

In this case, they are identical -- I'm speaking conceptually, that for me, it
is easier to consider allocations through new to be reserved for instances of
objects, and allocations through malloc to be raw memory.

Consider this:

class Base
{
public:
virtual int Override() { return 0; }
int n;
};

class Derived : public Base
{
public:
virtual int Override() { return 1; }
int x;
};

Derived * p = new Derived[15];

Try to explain in simple what p points to, and what you can and can't do w/ the
underlying allocated memory.

Contrast that with:

char * c = new char[15];

and why you can treat it differently.
 
J

Jeff Schwab

Julie said:
for me, it
is easier to consider allocations through new to be reserved for instances of
objects, and allocations through malloc to be raw memory.

It is good that you're keeping a conceptual line between raw memory and
typed memory. I don't think avoiding "new" for the raw memory is the
clearest way to express this, though. On the rare occasions when I
really want some raw memory, I typedef unsigned char to a type called
Byte, and work with Bytes as my raw memory. I've found type and
variable names the best places in my code to "self-document."

int main ( )
{
typedef unsigned char Byte;

Byte* raw_memory = new Byte[ 100 ];

// Work with raw memory...

delete [ ] raw_memory;
}
Derived * p = new Derived[15];

Try to explain in simple what p points to, and what you can and can't do w/ the
underlying allocated memory.

p points to the first element in an array of Derived objects.
Contrast that with:

char * c = new char[15];

c points to the first element in an array of char.
and why you can treat it differently.

Because Derived is not POD but char is.
 
T

tom_usenet

Claudio said:
There's no need whatsoever in C++ to use malloc/free, except to support legacy
code. new/delete should be used.

Explain to me how you reallocate a block to a smaller size using new w/o
copying?

I would have contemplated adding the following to the C++ language to
accommodate the allocation of (uninitialized) raw blocks of memory:

void * p = new void[size_in_bytes];

Then it would be possible to make the very real distinction between memory and
instance allocation.

Read up on operator new.

Tom
 
J

Julie

Jeff said:
for me, it
is easier to consider allocations through new to be reserved for instances of
objects, and allocations through malloc to be raw memory.

It is good that you're keeping a conceptual line between raw memory and
typed memory. I don't think avoiding "new" for the raw memory is the
clearest way to express this, though. On the rare occasions when I
really want some raw memory, I typedef unsigned char to a type called
Byte, and work with Bytes as my raw memory. I've found type and
variable names the best places in my code to "self-document."

int main ( )
{
typedef unsigned char Byte;

Byte* raw_memory = new Byte[ 100 ];

// Work with raw memory...

delete [ ] raw_memory;
}
Derived * p = new Derived[15];

Try to explain in simple what p points to, and what you can and can't do w/ the
underlying allocated memory.

p points to the first element in an array of Derived objects.
Contrast that with:

char * c = new char[15];

c points to the first element in an array of char.

Right! Which, conceptually, should be treated differently than an allocated
block of raw memory.
Because Derived is not POD but char is.

Right! I understand that there are special-class types, but feel that it can
be a sticking point for new learners of the language. Personally, I have no
problem w/ it because I stated w/ C and therefore had a basic understanding of
the POD types.

Part of my point is that you have to treat char as a non-POD type AND as an
allocation type for general purpose (raw) memory.

As I've said before, I think of it being more beneficial to think of new as an
allocator of instances of types, and malloc as an allocator of raw (untyped)
memory. My use of malloc is few and far between, so when it does happen, it is
usually very localized or well defined, and I have no problem keeping track of
the allocation scheme.

As I've stated, I would have preferred that new provide a method by which raw
(untyped) memory could be allocated, rather than allocating chars and calling
it raw. I've proposed

void * p = new void[size_in_bytes];

as reasonable candidate for such, although I realize that no such beast will be
making it into the standard, nor is this the forum to discuss such features.
 
J

Julie

tom_usenet said:
void* mem = ::eek:perator new(42);

I was not aware of this usage of new. Thank you for pointing it out.

I ammend my comments:

Raw memory should be allocated using the method you describe. Raw memory
allocated through new char[size] should be considered 'bad style'.

I was talking conceptually. I prefer to consider allocations (excepting your
method above) with new as allocations of instances of object(s).
 
J

Julie

tom_usenet said:
Claudio said:
There's no need whatsoever in C++ to use malloc/free, except to support legacy
code. new/delete should be used.

Explain to me how you reallocate a block to a smaller size using new w/o
copying?

I would have contemplated adding the following to the C++ language to
accommodate the allocation of (uninitialized) raw blocks of memory:

void * p = new void[size_in_bytes];

Then it would be possible to make the very real distinction between memory and
instance allocation.

Read up on operator new.

Done, thanks for pointing that out.

Regardless, I personally think that the intention of new void[] is somewhat
more clear, but this isn't the forum for such discussions.
 
T

tom_usenet

I ammend my comments:

Raw memory should be allocated using the method you describe. Raw memory
allocated through new char[size] should be considered 'bad style'.

Why? The lifetime of a POD object begins when storage of suitable
alignment becomes available. However, there doesn't seem a compelling
reason not to use operator new rather than new char[] - it may be more
efficient (in space) for one.
I was talking conceptually. I prefer to consider allocations (excepting your
method above) with new as allocations of instances of object(s).

You may prefer to consider allocations with new as allocations of
instances of object(s), but for POD types, it is no different from
using malloc or any other memory allocator. You know that of course,
so you're overstating your case somewhat.

Tom
 
C

Claudio Puviani

Julie said:
I ammend my comments:

Raw memory should be allocated using the method you describe. Raw memory
allocated through new char[size] should be considered 'bad style'.

Oh, for crying out loud! Just what credentials do you have to presume to dictate
style to people who have orders of magnitude more experience and knowledge than
you? So far, I haven't seen the slightest indication that you'd even recognize
good style, let alone be in a position to define it for others. You can say, "I
personally don't like that style," but it's laughable for you to try to define
what "good" style is on the basis of your ignorance of the language and its
idioms.

Claudio Puviani
 
J

Julie

Claudio said:
Julie said:
I ammend my comments:

Raw memory should be allocated using the method you describe. Raw memory
allocated through new char[size] should be considered 'bad style'.

Oh, for crying out loud! Just what credentials do you have to presume to dictate
style to people who have orders of magnitude more experience and knowledge than
you?

I wasn't trying to dictate -- I should have prefaced that with "I prefer to
consider ..."
So far, I haven't seen the slightest indication that you'd even recognize
good style,

I don't know that I've tried to indicate good style, as I usually stay out of
those discussions. Feel free to arrive at whatever conclusion you desire, I'm
not trying to impress you or anyone else on this forum.

Regardless, do you consider the following 'good style' or an 'accepted idiom'?

// allocate raw memory for image bits
void * p = (void *)new char[image_size];

(Note: I'm using C-style casts for brevity, substitute C++ style casts if you
prefer, the underlying idea is the same.)

Personally, I consider that there are more appropriate ways to allocate raw
memory rather than confusing the issue w/ a placeholder type such as char.

Previously, as I've stated, in the past I've used malloc for the allocation of
what I considered raw memory, and new char[] for the allocation of character
arrays. In the future, I'll use ::eek:perator new(size) for allocations of raw
memory, and new char[] for the allocation of characters arrays.
 

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,774
Messages
2,569,596
Members
45,144
Latest member
KetoBaseReviews
Top