为什么不应该在头文件中C ++操作符new / delete / variant? [英] Why shouldn't C++ operator new/delete/variants be in header files?
问题描述
有人可以解释这个C ++编译错误的本质吗?我正在深入/学习关于重载全局运算符new,delete和它们的变体。我阅读了情侣 of 文章 开 the 代码
foo.h
:
p>
#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
在包含在/usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include中的文件中/c++/ext/new_allocator.h:33:0,
来自/usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/c++/x86_64-pc-cygwin/bits/c++ allocator.h:33,
从/usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/c++/bits/allocator.h:46,
从/ usr / lib / gcc / x86_64-pc-cygwin / 5.4.0 / include / c ++ / string:41,
来自/usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/c++/bits/locale_classes。 h:40,
从/usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/c++/bits/ios_base.h:41,
从/ usr / lib / gcc / x86_64-pc-cygwin / 5.4.0 / include / c ++ / ios:42,
来自/usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/c++/ostream:38,
来自/usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/c++/iostream:39,
来自foo.cpp:2:
/ usr / lib / gcc / x86_64-pc-cygwin / 5.4.0 / include / c ++ / new:116:41:错误:声明'void operator delete(void *)noexcept'有不同的异常说明符
__attribute __((__ external_visible__));
^
在foo.cpp中包含的文件中:1:0:
./foo.h:8:6:错误:来自上一个声明void operator delete(void *)
void operator delete(void * p);
^
在/usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/c++/ext/new_allocator.h:33:0中包含的文件中,
从/ usr / lib / gcc / x86_64-pc-cygwin / 5.4.0 / include / c ++ / x86_64-pc-cygwin / bits / c ++ allocator.h:33,
从/ usr / lib / gcc / x86_64 -pc-cygwin / 5.4.0 / include / c ++ / bits / allocator.h:46,
来自/usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/c++/string:41 ,
来自/usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/c++/bits/locale_classes.h:40,
来自/ usr / lib / gcc / x86_64-pc -cygwin / 5.4.0 / include / c ++ / bits / ios_base.h:41,
来自/usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/c++/ios:42,
来自/usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/c++/ostream:38,
来自/usr/lib/gcc/x86_64-pc-cygwin/5.4.0 / include / c ++ / iostream:39,
来自foo.cpp:2:
/usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/c++/new:118:41 :错误:声明'void operator delete [](void *)noexcept'有一个不同的异常说明符
__attribute __((__ external_visible__));
^
在foo.cpp中包含的文件中:1:0:
./foo.h:9:6:error:from previous declaration'void operator delete [](void *) '
void operator delete [](void * p);
^
我认为相关的一些问题:
- 如果我在
foo.cpp中注释掉
,编译成功#include< iostream>
- 如果我注释掉
foo.h
中的函数声明,定义,foo.cpp
(并保留#include
),编译成功。 >
我有一些模糊的怀疑;也许回答者将通过他们的答案确认:
- 错误提及
异常说明符
所以我认为也许通过重写任何这些运算符,我不得不重写整个套子的兄弟姐妹。但是,添加操作符delete(void *,const std :: nothrow_t&)
声明和定义并没有改变编译错误。我也不认为应该是真的,覆盖任何这些操作员责备编码器实现所有这些,但我误认了吗? - 我读了一篇文章StackOverflow提到这些操作符只能包含在一个翻译单元中,因此不应该在头文件中。我不明白翻译单位是什么,该文没有解释它是什么。如果这是与这个问题,请解释一个翻译单位是什么,为什么需要从头文件中排除函数声明 - 这似乎与我所有以前的C ++编码经验。
感谢您的深入了解。
库声明运算符delete
函数作为:
void operator delete(void *)noexcept;
void operator delete [](void *)noexcept;
,并声明为:
void operator delete(void *);
void operator delete [](void *);
不要在.h文件中声明它们,而应使用
#include< new>
查找部分 18.6动态内存管理您可以访问该主题以获取有关主题的更多信息。
翻译单位通常是.cpp文件。进一步阅读:什么是翻译单元在C ++ 中。
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.
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++.
这篇关于为什么不应该在头文件中C ++操作符new / delete / variant?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!