перегрузка оператора new и удаление ошибки получения компилятора - PullRequest
2 голосов
/ 03 марта 2020

Я пытаюсь выполнить пример кода о «Перегрузке оператора» из книги по программированию. Тем не менее, у меня есть следующая ошибка:

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

Вот как я перегрузил новый оператор:

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
}

Вывод на консоль во время сборки:

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)

1 Ответ

1 голос
/ 03 марта 2020

Вы перегружаете неправильный оператор.

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

вызывает operator new[], а не operator new, потому что это выражение нового массива.

Итак, вы хотите перегрузить

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

не

void *operator new(size_t sz,int setvalue)

На практике вам, вероятно, следует перегружать оба (вы можете просто позвонить opearator new из operator new[]).

Вам также необходимо всегда перегружать operator delete и operator delete[] при перегрузке operator new и operator new[] соответственно.

Я не знаю, что делает memoryWarning();, но помните, что operator newoperator new[]) без спецификация не-генерирующего исключения должна генерировать исключение, которое может быть перехвачено catch(std::bad_alloc) в случае неудачного выделения. Возвращение нулевого указателя не допускается.

Наконец, перегрузка operator new, которую вы пытаетесь сформировать здесь, не работает так, как вы намереваетесь.

malloc не создает никаких объекты в памяти, которую вы выделяете. memset (если это даже технически разрешено здесь) запишет символ в эту память. Затем новое выражение создаст в этой памяти массив char.

Вновь созданные объекты не принимают значение, которое ранее имело место в памяти, в которую они помещены. Вместо этого значения char элементов массива будут неопределенны , и вам нужно будет снова их инициализировать.

Правильный способ сделать то, что вы пытаетесь здесь, - не перегружать operator new, но инициализировать массив вручную и желательно не с помощью стандартной библиотечной функции C memset, если у вас нет веских оснований для его использования. Вместо этого используйте, например, std::fill (требуется #include<algorithm>):

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

Или лучше используйте std::string (требуется #include<string>):

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

Указатель на базовый Массив char можно получить из str.data().


Также не используйте NULL. Начиная с C ++ 11 существует nullptr, который всегда безопаснее в использовании. Никогда не используйте NULL, всегда используйте nullptr.

...