【问题标题】:operator new already has a body操作员 new 已经有一个身体
【发布时间】:2012-08-22 11:34:23
【问题描述】:

我正在尝试使用全局参数来实现 operator new。如果没有 args 的 new 重载没有问题,但是在尝试编译时出现以下错误

inline void* operator new(size_t, void* p) {
    //...
    return p;
}

c:\bjarne_exercise_6.cpp(14): error C2084: function 'void *operator new(size_t,void *) throw()' has a body c:\program files\microsoft visual studio 10.0\vc\include\new(55) :参见之前对“new”的定义

c:\bjarne_exercise_6.cpp(40): error C2264: 'operator new' : 函数定义或声明错误;函数未调用

我刚刚解决了这个问题,你必须在#include stdafx.h 之前声明这个 不,不是真的。它编译得很好,但仍然没有调用这个函数,而是来自新头文件的版本。之所以如此,是因为新标头中已经定义了新位置(带有 2 个参数)。普通的 new (只有 1 个 size_t 参数)只在那里声明,所以你仍然可以重载它。因此,如果您想要具有超过 1 个参数的特殊新参数,则以下 @trion 建议的解决方案是合适的。

【问题讨论】:

  • 您有显示此问题的最小/完整程序吗?您的新产品和 main 可能会尝试使用它吗?
  • #include <new>了吗?不要inline
  • 我刚刚解决了这个问题,你必须在你之前声明这个#include stdafx.h
  • 但我仍然不清楚为什么 operator new(size_t) 即使在那时也编译得很好,但不是 new(size_t,void*p)。只有后者给出错误,两者都来自 并且在那里声明了
  • @cf16: void* operator new(size_t); 是为数不多的称为“可替换”的特殊函数之一,这意味着您可以定义它,即使实现是其他方式,如果您这样做,将使用您的定义。

标签: c++ operators new-operator


【解决方案1】:

operator new(如标准所称)的这种放置形式已经在全局命名空间中的 C++ 程序中定义,您不能自己在那里提供定义。不同于其他全球operator news,这个是不可替代的。

【讨论】:

  • 这是 Bjarne 书“C++ prog. lang”第 255 页中的示例
  • 好吧,好像他只是举了个例子,只是为了说明怎么做,因为他还说“它是在标准头文件中定义的”
【解决方案2】:

C++ 标准定义了一个位置operator new,在头文件<new> 中附加了一个void*。 它的实现类似于这样:

void* operator new(size_t, void* m)
{
    return m;
}

它通常用于在已分配的内存上实例化对象,例如通过将分配与实例化分开的 STL 容器。因此,如果您根据<new> 包含任何标准标头,则将已经定义了新的展示位置。

如果您想创建自己的具有不同语义的operator new 版本,可以使用虚拟参数来消除歧义:

struct my_new_dummy {} dummy;
void* operator new(size_t, my_new_dummy, void* m);

//...

int mem;
int* ptr = new(dummy, &mem) int;

编辑: 之所以可以重新定义普通的operator new 而不能重新定义placement new,是因为前者是编译器默认定义的,可以手动覆盖,而placement new 是定义的在标题中,因此会导致与您的重新定义发生冲突。

【讨论】:

  • 是的,这是一些解决方案,但问题仍然存在:为什么 operator new(size_t) 没有问题:它编译得很好,但不是 new(size_t,void*p)。只有后者给出错误
  • 已声明,未定义。那是有区别的。
  • 是的,这是真的。所以新的位置(带有2个参数)是在新标头中定义的,因此“有一个主体”错误,但是因为新的(只有1个,size_t参数)只在新标头中声明,你可以重载它。对吗?
  • 对。 <new> 中的声明与您自己的 new(size_t) 实现相匹配,就像 @aschepler 在对原始帖子的评论中所说的那样,只有在您自己不提供实现时,编译器才会定义 new(size_t)。
  • 这是如何实现的?如果我自己写了新的东西,我想有什么#defined?
【解决方案3】:

1) 你有编译错误,因为全局级别放置新运算符 不能 被替换!请参阅 c++ 11 标准(在以前的标准中也是如此)。

18.6.1.3 Placement forms [new.delete.placement]
1 These functions are reserved, a C++ program may not define functions that 

替换中的版本 标准 C++ 库 (17.6.4)。 (3.7.4) 的规定不适用于这些保留的放置形式 运算符 new 和运算符 delete。 void* operator new(std::size_t size, void* ptr) noexcept;

所以基本上你可以替换其他全局 new 运算符(见下文),但 NOT 按照标准禁止的放置形式!

void* operator new (std::size_t size) throw (std::bad_alloc) 

2) 另一方面,您可以编写自己的类级别的新运算符,包括在您的类中放置新的运算符,这没关系:

class Test
{
public:

    void* operator new (std::size_t size) throw (std::bad_alloc) {
        return malloc(size);
    }

    void* operator new (std::size_t size, const std::nothrow_t& nothrow_constant) throw() {
        return malloc(size);
    }

    void* operator new (std::size_t size, void* ptr) throw() {
        return malloc(size);
    }
};

【讨论】:

    【解决方案4】:

    是的。 operator new 的这种放置形式已在全局命名空间中定义,因此您无法自己在其中提供定义。这是不可替代的。

    【讨论】:

      猜你喜欢
      • 2012-06-20
      • 2013-10-21
      • 2017-08-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-16
      相关资源
      最近更新 更多