为什么C操作符新/删除/变体不能在头文件中?

有人可以解释这个C编译错误的本质吗?我正在努力学习如何重载全球操作符新增,删除和变体.我读了一个couple of articles on the subject,但我找不到一个似乎具体解决这个问题.

代码

foo.h中:

#ifndef foo_h
#define foo_h

void* operator new(size_t);
void* operator new[](size_t);

void operator delete(void*);
void operator delete[](void*);

#endif // foo_h

Foo.cpp中:

#include <foo.h>
#include <iostream>

void* operator new(size_t size) { return NULL; }
void* operator new[](size_t size) { return NULL; }

void operator delete(void* p) { }
void operator delete[](void* p) { }

编译错误

>g++ -g -std=c++14 -I./ -c foo.cpp -o foo.o
In file included from /usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/c++/ext/new_allocator.h:33:0,
                 from /usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/c++/x86_64-pc-cygwin/bits/c++allocator.h:33,
                 from /usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/c++/bits/allocator.h:46,
                 from /usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/c++/string:41,
                 from /usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/c++/bits/locale_classes.h:40,
                 from /usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/c++/bits/ios_base.h:41,
                 from /usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/c++/ios:42,
                 from /usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/c++/ostream:38,
                 from /usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/c++/iostream:39,
                 from foo.cpp:2:
/usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/c++/new:116:41: error: declaration of ‘void operator delete(void*) noexcept’ has a different exception specifier
   __attribute__((__externally_visible__));
                                         ^
In file included from foo.cpp:1:0:
./foo.h:8:6: error: from previous declaration ‘void operator delete(void*)’
 void operator delete(void* p);
      ^
In file included from /usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/c++/ext/new_allocator.h:33:0,
                 from /usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/c++/x86_64-pc-cygwin/bits/c++allocator.h:33,
                 from /usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/c++/bits/allocator.h:46,
                 from /usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/c++/string:41,
                 from /usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/c++/bits/locale_classes.h:40,
                 from /usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/c++/bits/ios_base.h:41,
                 from /usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/c++/ios:42,
                 from /usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/c++/ostream:38,
                 from /usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/c++/iostream:39,
                 from foo.cpp:2:
/usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/c++/new:118:41: error: declaration of ‘void operator delete [](void*) noexcept’ has a different exception specifier
   __attribute__((__externally_visible__));
                                         ^
In file included from foo.cpp:1:0:
./foo.h:9:6: error: from previous declaration ‘void operator delete [](void*)’
 void operator delete[](void* p);
      ^

关于这个问题的一些疑问,我认为是相关的:

>如果我注释掉#include< iostream>在foo.cpp中,编译成功
>如果我注释掉foo.h中的函数声明,并且只保留它们的定义,在foo.cpp(并保持#include< iostream>))中,编译成功.

我有一些模糊的怀疑;也许回答者将通过答案确认:

>这个错误提到了一个异常说明符,所以我认为也许通过覆盖任何这些运算符,我不得不覆盖整个他们的兄弟姐妹套件.但是,添加operator delete(void *,const std :: nothrow_t&)声明和定义没有改变编译错误.我也不认为,超越这些操作符必须要求编码人员实施所有这些操作符,但我错了吗?
>我在StackOverflow之外读过一篇文章,提到这些操作符只能包含在一个“翻译单元”中,因此不应该在头文件中.我不明白翻译单位是什么,那篇文章没有解释什么.如果这与这个问题有关,请说明一个“翻译单位”是什么,为什么必须从头文件中排除功能声明 – 这似乎与我以前的C编程经验相反.

感谢您的任何见解.

您所看到的问题是由于以下声明的差异.

该库声明运算符删除功能:

void operator delete(void*) noexcept;
void operator delete [](void*) noexcept;

而您将其声明为:

void operator delete(void*);
void operator delete [](void*);

不要在.h文件中声明它们,而应该使用它们

#include <new>

查找部分18.6如果您有权访问C 11标准以获取有关该主题的更多信息,则动态内存管理.

翻译单位通常是一个.cpp文件.进一步阅读:What is a “translation unit” in C++.

翻译自:https://stackoverflow.com/questions/39324281/why-shouldnt-c-operator-new-delete-variants-be-in-header-files

转载注明原文:为什么C操作符新/删除/变体不能在头文件中?