2

I am trying to execute a code example about "Operator Overloading" from a programming book. However, I have the following error:

invalid conversion from 'char' to 'void*' [-fpermissive]
      char *p= new ('$') char[100];

This is how I overload the new operator:

void *operator new(size_t sz,int setvalue)
{
    void *p;

    p=malloc(sz);
    if(p==NULL){
        memoryWarning();
    }
    memset(p,setvalue,sz);
    return(p);
}


int main()
{
    //rest of the code;
    char *p = new ('$') char[100];
    //rest of the code
}

Console output during build:

21:39:21 **** Incremental Build of configuration Debug for project chapter5a ****
Info: Internal Builder is used for build
g++ -O0 -g3 -Wall -c -fmessage-length=0 -std=c99 -o "src\\chapter5a.o" "..\\src\\chapter5a.cpp" 
cc1plus.exe: warning: command line option '-std=c99' is valid for C/ObjC but not for C++
<strong>..\src\chapter5a.cpp: In function 'int main()':
..\src\chapter5a.cpp:22:20: error: invalid conversion from 'char' to 'void*' [-fpermissive]
  char *p= new('$') char;*
                    ^~~~</strong>
In file included from C:/Program Files (x86)/mingw-w64/i686-6.4.0-posix-dwarf-rt_v5-rev0/mingw32/lib/gcc/i686-w64-mingw32/6.4.0/include/c++/ext/new_allocator.h:33:0,
                 from C:/Program Files (x86)/mingw-w64/i686-6.4.0-posix-dwarf-rt_v5-rev0/mingw32/lib/gcc/i686-w64-mingw32/6.4.0/include/c++/i686-w64-mingw32/bits/c++allocator.h:33,
                 from C:/Program Files (x86)/mingw-w64/i686-6.4.0-posix-dwarf-rt_v5-rev0/mingw32/lib/gcc/i686-w64-mingw32/6.4.0/include/c++/bits/allocator.h:46,
                 from C:/Program Files (x86)/mingw-w64/i686-6.4.0-posix-dwarf-rt_v5-rev0/mingw32/lib/gcc/i686-w64-mingw32/6.4.0/include/c++/string:41,
                 from C:/Program Files (x86)/mingw-w64/i686-6.4.0-posix-dwarf-rt_v5-rev0/mingw32/lib/gcc/i686-w64-mingw32/6.4.0/include/c++/bits/locale_classes.h:40,
                 from C:/Program Files (x86)/mingw-w64/i686-6.4.0-posix-dwarf-rt_v5-rev0/mingw32/lib/gcc/i686-w64-mingw32/6.4.0/include/c++/bits/ios_base.h:41,
                 from C:/Program Files (x86)/mingw-w64/i686-6.4.0-posix-dwarf-rt_v5-rev0/mingw32/lib/gcc/i686-w64-mingw32/6.4.0/include/c++/ios:42,
                 from C:/Program Files (x86)/mingw-w64/i686-6.4.0-posix-dwarf-rt_v5-rev0/mingw32/lib/gcc/i686-w64-mingw32/6.4.0/include/c++/ostream:38,
                 from C:/Program Files (x86)/mingw-w64/i686-6.4.0-posix-dwarf-rt_v5-rev0/mingw32/lib/gcc/i686-w64-mingw32/6.4.0/include/c++/iostream:39,
                 from ..\src\chapter5a.cpp:9:
C:/Program Files (x86)/mingw-w64/i686-6.4.0-posix-dwarf-rt_v5-rev0/mingw32/lib/gcc/i686-w64-mingw32/6.4.0/include/c++/new:146:14:<strong> note:   initializing argument 2 of 'void* operator new(std::size_t, void*)'
 inline void* operator new(std::size_t, void* __p) _GLIBCXX_USE_NOEXCEPT
              ^~~~~~~~</strong>

21:39:21 Build Finished (took 703ms)
walnut
  • 21,629
  • 4
  • 23
  • 59
praful h y
  • 45
  • 4
  • Your book appears deficient. I recommend a [good C++ book](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). `main` should return `int`, conflating `new` and [`new[]`](https://en.cppreference.com/w/cpp/memory/new/operator_new). – Eljay Mar 03 '20 at 12:56
  • In Visual Studio it does compile and work. Can you try changing the line to `char *p = (char*)(new ('$') char[100]);` and see if it works? What kind of compiler do you use? – Eric Mar 03 '20 at 13:13
  • I am using MinGW GCC – praful h y Mar 03 '20 at 13:40
  • Tried changing the line to `char *p = (char*)(new ('$') char[100])` it did'nt work. Same error. – praful h y Mar 03 '20 at 14:00
  • @Rixment It seems to work with MSVC on godbolt (even with `/permissive-`) as well. I don't know why MSVC thinks it can call `operator new` instead of `operator new[]` here without diagnostic. I can't find anything supporting that in the standard. Looks like a non-standard extension or a bug to me. – walnut Mar 03 '20 at 16:13
  • @prafulhy I hope the code you are showing is written by you and not a verbatim example from your book, because the whole idea of it is wrong, see my answer. – walnut Mar 03 '20 at 16:19
  • @walnut What I see, but I could be wrong as I haven't used cpp for a while, is the usage of new placement operator. – Eric Mar 03 '20 at 16:30
  • @Rixment But it is the wrong one. Since it is an array new expression it must call `operator new[]`, not `operator new`. If you look at the assembly you see that MSVC calls OP's `operator new` overload, which should not be considered. – walnut Mar 03 '20 at 16:35
  • @walnut I am using the code from the text book and is not written by me. I am a beginner, this is a simple example demonstrating overloading of global `new` and `delete` operators. And also i have tried replacing the line with `char *p= new ('$') char;` still I get the same error. – praful h y Mar 04 '20 at 05:11
  • I have now edited the post, I have attached the console output during the build. – praful h y Mar 04 '20 at 05:17
  • @prafulhy Then the book is wrong. I have explained why this doesn't work (at all) in my answer. This doesn't seem to be a good book. See [here](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) for a list of better ones. – walnut Mar 04 '20 at 08:39
  • @prafulhy Also, the option `-std=c99` to `g++` makes no sense. C99 is an iteration of the C language, not C++ language. Looking at the original form of the code in your question (if that is the form in which it appears in the book) it seems that the book might be teaching a pre-standardization version of C++? When was the book published? – walnut Mar 04 '20 at 08:43
  • Thank you @walnut. As you told the book is old. Published in year 2002 written by a local author in India. I ll definitely refer the books mentioned by you in the link. Thanks once again. – praful h y Mar 04 '20 at 09:26

1 Answers1

1

You are overloading the wrong operator.

char *p = new ('$') char[100];

calls operator new[], not operator new, because it is an array new expression.

So you want to overload

void *operator new[](size_t sz,int setvalue)

not

void *operator new(size_t sz,int setvalue)

In practice you should probably overload both (you can just call opearator new from operator new[]).

You also need to always overload operator delete and operator delete[] when you overload operator new and operator new[] respectively.

I don't know what memoryWarning(); does, but be aware that operator new (and operator new[]) without non-throwing exception specification must throw an exception that can be caught by catch(std::bad_alloc) when allocation fails. Returning a null pointer is not allowed.

Lastly the operator new overload you are trying to form here doesn't work the way you intend it to.

malloc does not create any objects in the memory you allocate. memset (if it is even technically allowed here) will write the character into that memory. Then the new expression will create the char array in that memory.

Newly created objects do not take on the value that the memory they are placed in had before. Instead the values of the char elements of the array will be indeterminate and you will need to initialize them again.

The correct way to do what you are trying here is not to overload operator new, but to initialize the array manually and preferably not with the C standard library function memset if you don't have a good reason to use it. Use e.g. std::fill instead (requires #include<algorithm>):

char *p = new char[100];
std::fill(p, p+100, '$');

Or better, use std::string (requires #include<string>):

std::string str(100, '$');

A pointer to the underlying char array can be obtained from str.data().


Also, don't use NULL. Since C++11 there is nullptr which is always safer to use. Never use NULL, always use nullptr.

walnut
  • 21,629
  • 4
  • 23
  • 59