1

我继承了一个 Visual Studio 6.0 项目以转换为 2005。它包括这个奇妙的 MyClass 类,客户端代码通过在它的实例上调用placement new 在任何地方使用它(这里大大简化了):

#include <new>
#include <cstdio>

template<class T>
class MyClass {
public:

    // This is what the author assumed would be called on placement new.
    inline friend void* operator new(size_t u_size, MyClass<T>& mc) {
        printf("MyClass friend placement new\n");
        // ...
        return 0;
    }

    // This is just to show koenig lookup works on normal functions.
    inline friend void hello(MyClass<T>& mc) {
        printf("Hello called with koenig lookup\n");
        // ...
    }

    // This was part of the original class, gets called further below.
    operator unsigned int*() {
        printf("Converting for default placement new\n");
        // ...
        return 0;
    }
};

/* This gets called in VS2005 if un-commented.
template<class T>
void* operator new(size_t u_size, MyClass<T>& mc) {
    printf("MyClass placement new non-friend non-inline\n");
    // ***
    return 0;
}
*/

class DummyClass {    
   int a;
};

void testfunction() {
    MyClass<DummyClass> mc;
    hello(mc);
    void* a = new(mc) DummyClass; // Placement new call

    char c;
    gets(&c);
}

当我在 VS2005 中运行“testfunction()”时,在放置 new 调用时,MyClass 中的运算符“inline friend void* operator new(...)”永远不会被调用。取而代之的是,“operator unsigned int*()”被调用,结果被强制转换为 void*,并且默认的放置操作符 new 被调用(所以“转换为默认放置 new”被显示)。

在 VS6 中,placement new 改为在 MyClass 中调用“inline friend void* operator new(...)”(因此显示“CMyClass friend placement new”),这是作者的意图,但随后 VS6 在一种奇怪的方式。

为什么 VS2005 不能识别使用参数相关查找的内联友元放置运算符 new?它使用参数识别 hello() 函数(因此显示“使用 koenig 查找调用 Hello”),但它不适用于放置 new。

作为参考,无论 MyClass 是否被模板化,这似乎都会发生(但为了完整起见,我将其保留为模板化)。此外,如果您在 MyClass 之外取消注释非朋友“operator new”,则该操作在 VS2005 中会被正确调用。

是什么赋予了?里面有错误吗?新位置是依赖于参数的查找的特例吗?VS2005是对还是错?这里的标准 C++ 是什么?

对于一种解决方法,我打算使用非内联朋友而不是内联,但是对于前锋和所有人来说,这变得很难看,我想先问一下这里的交易是什么。

4

1 回答 1

4

问题是分配函数是在全局范围内查找的,而不是使用 ADL 查找的。由于在类中定义的友元函数在封闭范围内是隐藏的,因此找不到该函数。

5.3.4/9:

如果 new-expression 以一元 :: 运算符开头,则在全局范围内查找分配函数的名称。否则,如果分配的类型是类类型 T 或其数组,则在 T 的范围内查找分配函数的名称。如果查找失败,或者分配的类型不是类类型,则分配在全局范围内查找函数的名称。

于 2010-03-06T21:01:25.247 回答