“似乎”在语言标准中

时间:2010-02-21 16:52:29

标签: c++ standards standards-compliance

标准中“似乎”一词的确切含义是什么?当用户可以修改行为的各个部分时,它是如何工作的。

在谈论operator new的nothrow版本时,问题在于C ++标准。 18.4.1.1/7读(我的重点):

  

这个nothrow版本的operator new返回一个从普通版本获得的指针>。

我的理解是,只要行为合适,“似乎”不需要特定的实现。所以如果operator new像这样实现(我知道这不是一个兼容的实现,因为没有循环或使用new_handler;但我正在缩短它以专注于我的问题):

// NOTE - not fully compliant - for illustration purposes only.
void *operator new(std::size_t s)
{
    void *p = malloc(s);
    if (p == 0)
        throw std::bad_alloc();
    return p;
}

然后写下这样的nothrow版本是合法的:

// NOTE - not fully compliant - for illustration purposes only.
void *operator new(std::size_t s, const std::nothrow_t &nt)
{
    return malloc(s);
}

但是,假设程序替换operator new以使用其他分配器。 “似乎”意味着编译器必须自动更改nothrow版本的行为才能使用其他分配器吗?开发人员是否需要更换普通版本和非版本版本?

3 个答案:

答案 0 :(得分:7)

从1.9“程序执行:

  

符合实现需要模拟(仅)抽象机器的可观察行为

并在信息脚注中:

  

这项规定有时被称为“假设”规则,因为只要结果好像符合要求,实施可以自由地忽视本国际标准的任何要求,只要可以从程序的可观察行为。例如,实际实现不需要评估表达式的一部分,如果它可以推断出它的值没有被使用,并且没有产生影响程序的可观察行为的副作用。

该标准特别注意到“as-if”要求是对operator new()的nothrow版本的替换版本具有约束力。但是,正如我所读到的那样,该要求将由程序员覆盖operator new()而不是编译器。这个责任的另一面是我认为标准几乎要求库提供的nothrow operator new()的默认实现必须在try / catch中调用throw new这样做。如果发现std::bad_alloc,则返回0。

在这里可以使用“似乎规则”的情况是,如果编译器/链接器/其他任何内容足够聪明,可以确定当使用默认投掷new()时,默认非投掷new()可以使用快捷方式,但如果默认投掷new()被覆盖,则默认非投掷new()必须采取不同的行动。我确信这在技术上是可行的(即使你可能无法在标准C ++中表达)。如果有任何实现可以做到这一点,我会感到惊讶。

我可能会过多地阅读这个要求,但我认为这是可以推断的。

答案 1 :(得分:2)

如果operator new中分配器的更改在兼容的C ++程序的行为中产生了可观察到的差异,那么可能需要更改 no-throw 版本的实现。特别是如果operator delete只期望新分配器分配的块,则 no-throw new必须更改。

我的阅读是,当用户没有覆盖标准operator new时,使用就像一样可以实现你的实现。一旦他有,实现不能使用基于malloc no-throw operator new,并且必须明确地调用用户声明的版本或至少重新使用用户声明版本符合程序无法判断这不是 no-throw 版本的实现方式。

答案 2 :(得分:0)

开发人员应该替换plain和nothrow版本。在GOTW上查看此article

我的假设是标准将要求放在编译器(和运行时)默认实现上。因此,您引用的“似乎”旨在通知编译器供应商,这些方法的默认实现必须满足指定的条件。如果开发人员选择仅覆盖operator new的一个版本,我认为编译器不负责使所有其他版本的operator new兼容。这是开发人员的责任。但这就是我的全部意见,我现在没有方便的规范来看看它在前面的内容中说了什么。