2

Not using below thing anywhere but still this question was in my mind for long.

void* operator new (size_t size)
{
  // distort `size` to other value
  return malloc(size);
}

Having know that above may not be a well-defined behavior for overloaded new (say if the size is decreased), Why doesn't standard force compilers to make it as void* operator new (const size_t); ?

The same can be argued for operator delete also, where it should void operator delete (void* const); (adding const to avoid pointer getting changed).

iammilind
  • 68,093
  • 33
  • 169
  • 336
  • You already had a bunch of good answer. To learn more about this, also have a look at [How to pass objects to functions in C++](http://stackoverflow.com/q/2139224/140719). – sbi Jul 22 '11 at 12:35

5 Answers5

8
void* operator new (const size_t n);
void* operator new (size_t n);

These two are completely identical declarations of operator new. The only difference is that if it were a definition, n would be or wouldn't be allowed to be modified inside the function body (which would be irrelevant to the caller, since the parameter is passed by value). Since that is an implementation detail, the standard doesn't talk about it.

Remember, top-level const's are ignored in function declarations. They're relevant only in definitions.

Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434
  • Can you clarify "top-level"? I am thinking of references. Constness of a reference refers to constness of the referred-to object because the reference *itself* is always immutable. – spraff Jul 22 '11 at 12:48
  • @spraff: No, a reference cannot be const-qualified at all. `int*const` has a top-level const. `const int *` - here const is not top-level – Armen Tsirunyan Jul 22 '11 at 12:57
  • Can you cite chapter and verse for this, please? I get the feeling we're drifting from the right terminology. – spraff Jul 22 '11 at 12:59
  • @Spraff: Read 13.1.3 - second example from the end – Armen Tsirunyan Jul 22 '11 at 13:09
6

The type of the argument in both cases, const std::size_t and plain std::size_t is std::size_t. The standard dictates that when processing a function signature in a declaration (later on definitions), the const is dropped from the type. The specific paragraph is in §8.3.5/3:

[...] After producing the list of parameter types, several transformations take place upon these types to determine the function type. Any cv-qualifier modifying a parameter type is deleted. [Example: the type void()(const int) becomes void()(int) —end example]

Now, in the definition of the function, the const does have the effect that you propose: blocking you from modifying the argument. You are free to implement your operator new with a const std::size_t argument. On the other hand, enforcing that would be basically useless. As others have mentioned, the fact that the argument is const can be subverted by copying it to a different variable and using that variable. There is no point in adding the extra burden of verification to the compilers when it does not add real value to the language.

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
2

Const-ness for non-reference arguments is of only marginal importance.

The standards defines "important" things from the point of view of the caller.

Constness of these by-value arguments does not and cannot change any code which uses them. The implementer can look after themselves.

Update: you can write it this way if you want.

int f (const int);
int f (int) {return 0;}

int main () {
    int i;
    f (i);
}

I didn't get any errors with the above. Go ahead and const-ify your size_t :-)

To anticipate an objection: here f stands-in for operator new or whatever. So we have a contradicting declaration/definition, yet the compiler doesn't complain. Why? Because it just doesn't matter.

spraff
  • 32,570
  • 22
  • 121
  • 229
  • 1
    however the spec says " The first parameter shall have type std::size_t (18.2). ". That seems to forbid `const size_t`. It doesn't say the parameter-type-list or its signature shall have a first parameter of type `size_t`. It's ambiguous to me: One could interpret it as allowing `size_t`, but one could also interpret it as disallowing it. I tend to interpret it as allowing `const size_t` though. – Johannes Schaub - litb Jul 22 '11 at 11:21
  • I agree. But I have seen that most of the time compilers also care about trivial things. I found `const size_t` trivial. – iammilind Jul 22 '11 at 11:23
  • I'm not sure I follow you exactly, but it seems to me that ambiguity *does not matter* in this case -- they are **equivalent** and **interchangeable** from the point of view of the caller. Qui bono? – spraff Jul 22 '11 at 11:24
  • 1
    The standard dictates that that particular `const` is not part of the signature of the function (in the declaration). As per §8.3.5/3: *After producing the list of parameter types, several transformations take place upon these types to determine the function type. Any cv-qualifier modifying a parameter type is deleted. [Example: the type void(*)(const int) becomes void(*)(int) —end example]* The declaration with and without `const` declare the exact same thing. – David Rodríguez - dribeas Jul 22 '11 at 12:46
2

Okay, let's pretend it is const:

void* operator new (const size_t size)
{
   size_t alteredSize = size;
   alteredSize += 10; // for whatever reason
   return malloc( alteredSize );
}

which is completely the same as

void* operator new (size_t size)
{
   size += 10;
   return malloc( size );
}

const on parameters that are copied into the function (passed by value) doesn't enforce using that value - the function can create a writable copy and alter that copy.

spraff
  • 32,570
  • 22
  • 121
  • 229
sharptooth
  • 167,383
  • 100
  • 513
  • 979
  • No, this is related to compile time checks. Say for example, you `return 0;` from `operator new` and compiler warn you. What you say is just **shoot your foot** kind of example. – iammilind Jul 22 '11 at 11:21
  • 1
    You are not allowed to change a `const size_t`. The second example code you show is ill-formed. – Johannes Schaub - litb Jul 22 '11 at 11:22
  • @Johannes Schaub - litb: I don't get it. Why is it `const` there? – sharptooth Jul 22 '11 at 11:30
  • @sharp I don't get it. It was const there because you made it const. Can you elaborate on what your question is? – Johannes Schaub - litb Jul 22 '11 at 11:35
  • @Johannes Schaub - litb: In the first definition `size` has `const` qualifier but it doesn't have a `const` qualifier in the second definition. You say *the second code* is ill-formed and I don't get why it is ill-formed. – sharptooth Jul 22 '11 at 11:42
  • 1
    Because before the edit your 2nd definition looked like `operator new (const size_t size);` and then you were doing `size += 10;` – iammilind Jul 22 '11 at 11:47
1

You have already received many good answers on operator new. One more argument for not making the size argument to operator new const: An overriding implementation may well want to allocate more space than was requested, such as for cookies, guard words, etc.

The same can be argued for operator delete also, where it should void operator delete (void* const); (adding const to avoid pointer getting changed).

On most modern operating systems that use virtual memory, free does not necessarily release the allocated memory to the OS. That memory may still well be in the program's virtual space. A pedantic overrider may well want to fill the pointed-to memory with absolute garbage prior to deleting it to further invalidate subsequent use of that memory by the calling function. The calling function must not use the pointed-to memory after having deleted it, so why hobble operator delete with an unneeded restriction?

David Hammen
  • 32,454
  • 9
  • 60
  • 108