【问题标题】:operator overloading new and delete getting compiler error运算符重载new和delete得到编译器错误
【发布时间】:2020-03-03 12:23:50
【问题描述】:

我正在尝试从编程书中执行有关“运算符重载”的代码示例。但是,我有以下错误:

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

这就是我重载 new 运算符的方式:

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)

【问题讨论】:

  • 您的书似乎有缺陷。我推荐good C++ bookmain 应该返回 int,合并 newnew[]
  • 在 Visual Studio 中它确实可以编译和工作。您可以尝试将线路更改为char *p = (char*)(new ('$') char[100]); 并查看它是否有效?你使用什么样的编译器?
  • 我正在使用 MinGW GCC
  • 尝试将行更改为char *p = (char*)(new ('$') char[100]) 它不起作用。同样的错误。
  • @Rixment 它似乎也适用于 Godbolt 上的 MSVC(即使是 /permissive-)。我不知道为什么 MSVC 认为它可以在这里调用 operator new 而不是 operator new[] 而无需诊断。我在标准中找不到任何支持它的东西。对我来说,这看起来像是一个非标准扩展或错误。

标签: c++ compiler-errors operator-overloading new-operator


【解决方案1】:

你重载了错误的操作符。

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)

实际上,您可能应该同时重载两者(您可以从operator new[] 调用opearator new)。

当您分别重载operator newoperator new[] 时,您还需要始终重载operator deleteoperator delete[]

我不知道memoryWarning(); 做了什么,但请注意,没有非抛出异常规范的operator new(和operator new[])必须抛出一个异常,当分配失败时catch(std::bad_alloc) 可以捕获该异常。不允许返回空指针。

最后,您尝试在此处形成的 operator new 重载无法按您的预期方式工作。

malloc 不会在您分配的内存中创建任何对象。 memset(如果技术上允许的话)会将字符写入该内存。然后新表达式将在该内存中创建char 数组。

新创建的对象不会采用它们所在的内存之前的值。相反,数组的char 元素的值将是indeterminate,您需要再次初始化它们。

您在这里尝试的正确方法不是重载operator new,而是手动初始化数组,如果您没有充分的理由使用,最好不要使用C标准库函数memset它。使用例如改为std::fill(需要#include&lt;algorithm&gt;):

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

或者更好,使用std::string(需要#include&lt;string&gt;):

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

可以从str.data()获得指向底层char数组的指针。


另外,不要使用NULL。自 C++11 以来,nullptr 使用起来总是更安全。永远不要使用NULL,始终使用nullptr

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-04
    • 2014-03-26
    • 2013-03-12
    • 1970-01-01
    • 1970-01-01
    • 2012-11-10
    相关资源
    最近更新 更多