问题
Can someone explain the nature of this C++ compile error? I am dabbling in/learning about overloading the global operators new, delete, and their variants. I read a couple of articles on the subject, but I couldn't find one that seems to address this specifically.
The Code
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) { }
The Compile Error
>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);
^
Some oddities about this issue that I think are relevant:
- If I comment out
#include <iostream>
infoo.cpp
, compilation succeeds - If I comment out the function declarations in
foo.h
, and only keep their definitions, infoo.cpp
(and also keeping#include <iostream>
), compilation succeeds.
I have some vague suspicions; perhaps answerers will confirm by way of their answers:
- The error makes mention of an
exception specifier
so I thought maybe by overriding any of these operators, I am obliged to override the entire suite of their siblings. However, addingoperator delete(void*, const std::nothrow_t&)
declaration and definition did not change the compile error. I also don't think it should be true that overriding any of these operators obliges the coder to implement all of them, but am I mistaken on that? - I read an article outside of StackOverflow mentioning that these operators must only be included in one "translation unit" and therefore should not be in header files. I don't understand what a translation unit is, and that article did not explain what it is. If that is related to this problem, please explain what a "translation unit" is and why that necessitates exclusion of function declarations from a header file - this seems contrary to all my prior C++ coding experience.
Thank you for any insight.
回答1:
The problem you are seeing is due to differences in the following declarations.
The library declares the operator delete
functions as:
void operator delete(void*) noexcept;
void operator delete [](void*) noexcept;
while you declare them as:
void operator delete(void*);
void operator delete [](void*);
Instead of declaring them in your .h file, you should use
#include <new>
Lookup section 18.6 Dynamic memory management of the C++11 standard if you have access to it for more information on the subject.
A translation unit is usually a .cpp file. Further reading: What is a "translation unit" in C++.
来源:https://stackoverflow.com/questions/39324281/why-shouldnt-c-operator-new-delete-variants-be-in-header-files