2016-09-05 123 views
12

有人可以解释这个C++编译错误的性质吗?我正在研究/学习如何重载全球运营商的新增,删除及其变体。我读了一个coupleofarticlesonthesubject,但我找不到一个似乎专门解决这个问题。为什么C++运算符new/delete/variants不在头文件中?

守则

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); 
    ^

对这个问题有些古怪,我认为是相关的:

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

我有一些模糊的怀疑;也许应答者将他们的答案的方式确认:

  • 该错误使得一个exception specifier提及,所以我想也许通过重写这些运营商的,我不得不重写他们的兄弟姐妹的整个套件。但是,添加operator delete(void*, const std::nothrow_t&)声明和定义并没有改变编译错误。我也不认为覆盖任何这些运营商都要求编码器实施所有这些运营商是不对的,但我误解了这一点吗?
  • 我读了一篇StackOverflow以外的文章,提到这些操作符只能包含在一个“翻译单元”中,因此不应该放在头文件中。我不明白翻译单位是什么,这篇文章没有解释它是什么。如果这与这个问题有关,请解释一下“翻译单元”是什么以及为什么需要从头文件中排除函数声明 - 这似乎与我之前的所有C++编码经验相反。

谢谢你的任何见解。

回答

5

您看到的问题是由于以下声明中的差异。同时声明他们作为

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

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

而是在你宣布他们

库声明operator delete功能。h文件,你应该使用

#include <new> 

查找部分18.6动态内存管理的C++ 11个标准,如果你有机会获得它关于这一主题的更多信息。

翻译单元通常是一个.cpp文件。更多阅读:What is a "translation unit" in C++

+1

你的回答让我意识到编译器错误实际上告诉我究竟是什么问题。我不好审查它,但谢谢你;你的回答帮助我填补了这个空白。 – StoneThrow

+0

这很奇怪,因为我无法再现同样的错误,并且我复制了问题中发布的完全相同的代码。如果这真的是问题,为什么我没有得到错误?顺便说一句,我使用VS 2015. –

+0

@MuhammadAhmad,我不知道为什么你没有得到任何错误。这是值得搜索。 –

相关问题