为什么不应该在头文件中C ++操作符new / delete / variant? [英] Why shouldn't C++ operator new/delete/variants be in header files?

查看:326
本文介绍了为什么不应该在头文件中C ++操作符new / delete / variant?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有人可以解释这个C ++编译错误的本质吗?我正在深入/学习关于重载全局运算符new,delete和它们的变体。我阅读了情侣 of 文章 the

代码

strong>



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> in foo.cpp, compilation succeeds
  • If I comment out the function declarations in foo.h, and only keep their definitions, in foo.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, adding operator 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆