“好像”在语言标准方面

发布于 2024-08-22 00:10:01 字数 872 浏览 2 评论 0原文

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

当谈论 operator new 的无抛出版本时,问题是关于 C++ 标准的。 18.4.1.1/7 读取(我的重点):

此运算符 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;
}

那么它像这样编写无抛出版本是合法的:

// 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以使用其他分配器。 “好像”是否意味着编译器必须自动更改 nothrot 版本的行为才能使用其他分配器?开发者是否需要同时替换普通版本和无抛出版本?

What is the exact meaning of the phrase "as if" in the standard and how does it work when a user can modify individual parts of the behavior.

The question is in regards to the C++ standard when talking about the nothrow version of operator new. 18.4.1.1/7 reads (my emphasis):

This nothrow version of operator new returns a pointer obtained as if acquired from the ordinary version.

My understanding is that "as if" does not require a specific implementation as long as the behavior is appropriate. So if operator new was implemented like this (I know this is not a compliant implementation as there is no loop or use of the new_handler; but I'm shortening that to focus on my issue):

// 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;
}

Then it would be legal to write the nothrow version like this:

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

But let's say a program replaces operator new to use some other allocator. Does "as if" mean the compiler has to automatically change the behavior of the nothrow version to use this other allocator? Is the developer required to replace both the plain and nothrow versions?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

诠释孤独 2024-08-29 00:10:02

开发人员应该替换普通版本和无抛出版本。查看 GOTW 上的这篇文章

我的假设是该标准对编译器(和运行时)默认实现提出了要求。因此,您引用的“好像”是为了通知编译器供应商,这些方法的默认实现必须满足指定的标准。如果开发人员选择仅覆盖一个版本的operator new,我认为编译器没有责任使所有其他版本的operator new 兼容。这是开发商的责任。但这就是我的全部观点,我目前手边没有规范,无法查看前面的内容。

The developer should replace both the plain and nothrow versions. Check out this article on GOTW.

My assumption is that the standard puts requirements on compiler (and runtime) default implementations. So the "as if" you quote is meant to inform the compiler vendor that its default implementations of those methods must meet the specified criteria. If a developer chooses to override only one version of operator new, I do not think it is the compiler's responsibility to make all other versions of operator new compliant. It is the developer's responsibility. But that's all my opinion, I don't have the spec handy at the moment to see what it says in the front matter.

风吹雪碎 2024-08-29 00:10:01

从1.9》程序执行:

需要一致的实现来模拟(仅)抽象机的可观察行为

,并在信息脚注中:

该规定有时被称为“假设”规则,因为实施可以自由地忽略本国际标准的任何要求,只要结果就像遵守了要求一样,只要可以确定程序的可观察行为。例如,如果实际实现可以推断出其值未被使用并且不会产生影响程序可观察行为的副作用,则实际实现不需要评估表达式的一部分。

该标准确实特别指出,“as-if”要求绑定在 operator new() 的 nothrow 版本的替换版本上。然而,当我读到它时,这个要求将落到程序员的头上,而不是编译器重写operator new()。这种责任的另一面是,我认为标准几乎要求库提供的 nothrow 运算符 new() 的默认实现必须执行与调用 throwing new 类似的操作 在 try/catch 中,如果捕获了 std::bad_alloc 则返回 0。

“好像规则”在这里发挥作用的地方是,如果编译器/链接器/任何东西足够聪明,能够弄清楚当使用默认抛出 new() 时,默认的非- 抛出 new() 可以采用快捷方式,但如果默认抛出 new() 被覆盖,则默认的非抛出 new()就必须采取不同的行动。我确信这在技术上对于实现来说是可能的(即使您可能无法用标准 C++ 来表达它)。如果有一个实现可以做到这一点,我会感到惊讶。

我可能对需求的解读太多了,但我认为这是可以推断的。

From 1.9 "Program execution:

conforming implementations are required to emulate (only) the observable behavior of the abstract machine

and in an informational footnote:

This provision is sometimes called the “as-if” rule, because an implementation is free to disregard any requirement of this International Standard as long as the result is as if the requirement had been obeyed, as far as can be determined from the observable behavior of the program. For instance, an actual implementation need not evaluate part of an expression if it can deduce that its value is not used and that no side effects affecting the observable behavior of the program are produced.

The standard does specifically note that the "as-if" requirement is binding on a replacement version of the nothrow version of operator new(). However, as I read it, that requirement would fall to the programmer overriding operator new() not the compiler. The flip side of this responsibility is that I think the standard pretty much requires the default implementation of the nothrow operator new() provided by the library must do something along the lines of calling the throwing new in a try/catch and return 0 if std::bad_alloc is caught.

Where the "as if rule" could come in to play here is if the compiler/linker/whatever were smart enough to figure out that when the default throwing new() was in being used, the default non-throwing new() could take the shortcut, but if the default throwing new() was overridden, the default non-throwing new() would have to act differently. I'm sure this is technically possible for an implementation (even if you probably can't express it in standard C++). I'd be surprised if there was ever an implementation that did this.

I might be reading too much into the requirement, but I think that's what can be inferred.

萌辣 2024-08-29 00:10:01

如果 operator new 中分配器的更改对兼容的 C++ 程序的行为产生了明显的差异,那么是的,它可能需要更改 no-throw 的实现版本。具体来说,如果operator delete期望仅由新分配器分配块,则no-throw new必须更改。

我的理解是,当用户没有覆盖标准operator new时,使用as if允许像您这样的实现。一旦他这样做了,实现就不能使用基于mallocno-throwoperator new并且必须显式调用用户声明的版本或至少重复使用足够多的用户声明版本,使符合标准的程序无法判断这不是无抛出版本的实现方式。

If the change in allocator in operator new makes an observable difference in the behaviour of a compliant C++ program then yes, it might require a change in the implementation of the no-throw version. Specifically if operator delete expects only blocks allocated by the new allocator then the no-throw new must change.

My reading is that the use of as if allows an implementation such as yours when the user hasn't overriden the standard operator new. As soon as he has, the implementation must not use a malloc based no-throw operator new and must either call the user declared version explicitly or at least re-use enough of the user declared version that a conforming program cannot tell that this isn't how the no-throw version has been implemented.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文