代码之家  ›  专栏  ›  技术社区  ›  sharptooth

我怎么能明智地超载?

  •  20
  • sharptooth  · 技术社区  · 14 年前

    C++允许重载 operator new 新操作员 , operator new[] new[] 陈述和安排 新操作员 分开。

    这三种方法中的前两种通常会因使用自定义分配器和添加跟踪而过载。但是安置 新操作员

    //from new.h
    inline void* operator new( size_t, void* where )
    {
       return where;
    }
    

    新操作员 ?

    9 回复  |  直到 14 年前
        1
  •  17
  •   GManNickG    14 年前

    正确答案是 不能将操作符放置替换为新

    §18.4.1.3安置形式
    这些函数是保留的,C++程序可能无法定义在标准C++库中替换版本的函数。

    理由:allocation和deallocation操作符的唯一目的是分配和释放内存,因此在给定内存时,不应再做任何事情。(该标准特别指出,这些功能“故意不执行其他操作”。)

        2
  •  4
  •   Bart van Ingen Schenau    14 年前

    operator new 有吗 这需要额外的参数,除了所需的内存大小。

    所以, new(std::nothrow) X 使用放置 新操作员 我也是 new(__FILE__, __LINE__) X .

    operator new(size_t, void*)

        3
  •  3
  •   blgt    10 年前

    One example 在Stroustrup的FAQ上。

        4
  •  1
  •   Matthieu M.    14 年前

    另一个明智的做法是添加一些检查(例如,验证请求区域中没有“绑定标记”)。

    然而,我认为这一点不仅仅是你必须重写它,只要你重写其他的(对于一个给定的类),因为名称查找的机制(或者不重写它来阻止它的使用,这也很好,但是这是一个有意识的决定)。

        5
  •  1
  •   Jesus    9 年前

    为预先保留的区域定义自己的内存管理是一个很好的用法。

    将此功能与文件的内存映射相结合,可以大大提高性能。 内存映射硬件。。。

        6
  •  0
  •   Cubbi    14 年前

    我见过一个例子,其中两个参数new[]被覆盖,以返回预先填充了作为附加参数传递的字符的内存块。我不记得原始代码使用了什么(可能是memset()),但在功能上是这样的:

    #include <iostream>
    #include <algorithm>
    #include <new>
    void* operator new [](size_t n, char c)
    {
            char* p = new char[n];
            std::fill(p, p+n, c);
            return p;
    }
    int main()
    {
            char* p = new('a') char[10];
            std::cout << p[0] << p[1] << ".." << p[9] << '\n';
    }
    

    虽然我猜这不会被称为“安置”新的,因为它不执行 安置 . 如果将其模板化,以便它可以构建任何类型的数组,并填充作为第二个参数传递的对象的副本,那么它可能会很有用。。。但不管怎样,我们都有集装箱。

        7
  •  0
  •   Carl Cook    11 年前

    我不太清楚这个问题,但以下是课堂上的新安排:

    struct Bar {
    void* operator new(size_t /* ignored */, void* where) throw() { return where; }
    };
    
    int main() {
      char mem[1];
      Bar* bar = new(mem) Bar;
    }
    

    我相信这是合法的C++(并且用GCC 4.4.6编译并运行良好)。

    您可以根据需要随意更改此运算符的实现(包括删除 throw() 子句,这意味着编译器不再检查 where 在调用构造函数之前为null的指针)。但要小心行事。

        8
  •  0
  •   Pavel Holoborodko    10 年前

    放置新重载最重要的额外功能是检查地址对齐。

    当他试着用他的类库使用新的布局时,一切都很好。。。库不知道类和它试图“放置”对象的地址是否需要对齐/需要什么样的对齐方式可能没有对齐-大爆炸。

    重载放置新的允许检测指针是否未对齐-可能节省调试时间。

        9
  •  -1
  •   RED SOFT ADAIR    14 年前

    我的主要用途是创建一个大的对象数组。它的性能要好得多,而且在整个块中分配内存的开销也更小,即使用Win32中的VirtualAlloc(在编程windows时)。然后您只需将该块中的ptr传递给每个新对象,例如:

    char *cp = new char[totalSize];
    
    for(i = 0; i < count; i++, cp += ObjSize)        
    {                                                        
        myClass *obj = new(cp) myClass;             
    }