在某些情况下,我们使用标签来区分函数。标签通常是一个空结构:
struct Tag { };
Run Code Online (Sandbox Code Playgroud)
假设我有一个使用此标签的函数:
void func(Tag, int a);
Run Code Online (Sandbox Code Playgroud)
现在,我们调用这个函数:
func(Tag(), 42);
Run Code Online (Sandbox Code Playgroud)
并检查生成的 x86-64 反汇编,godbolt:
mov edi, 42
jmp func(Tag, int) # TAILCALL
Run Code Online (Sandbox Code Playgroud)
没关系,标签得到了完全优化:没有为其分配寄存器/堆栈空间。
但是,如果我查看其他平台,就会发现该标签存在一些。
在 ARM 上,r0用作标签,并且它被归零(似乎没有必要):
mov r1, #42
mov r0, #0
b func(Tag, int)
Run Code Online (Sandbox Code Playgroud)
对于 MSVC,ecx被用作标记,并且它是从堆栈中“初始化”的(同样,似乎没有必要):
movzx ecx, BYTE PTR $T1[rsp]
mov edx, 42 ; 0000002aH
jmp void func(Tag,int) ; func
Run Code Online (Sandbox Code Playgroud)
我的问题是:是否有一种标签技术在所有这些平台上都得到了同样的优化?
注意:我没有找到 SysV ABI 指定可以在参数传递时优化空类的地方...(甚至,Itanium C++ ABI说:“空类的传递与普通类没有什么不同”。)
引用标准:
using 指令指定指定命名空间中的名称可以在 using 指令出现在 using 指令之后的范围内使用。在非限定名称查找 (3.4.1) 期间,名称看起来好像是在最近的封闭名称空间中声明的,该名称空间包含 using 指令和指定名称空间。
看看这段代码:
namespace A {
int fn() { return 1; }
}
namespace Inner {
int fn() { return 2; }
namespace B {
using namespace A;
int z = fn();
}
}
Run Code Online (Sandbox Code Playgroud)
在这里,在我知道命名空间的确切规则之前,我曾期望z将其初始化为 1,正如我所写的那样using namespace A,因此预计A::fn()将使用它。但事实并非如此,z将被初始化为2,Inner::fn()因为我引用的规则而被称为。
这种行为背后的基本原理是什么:“好像它们是在最近的包含 using 指令和指定命名空间的封闭命名空间中声明的”?
如果using namespace为该命名空间中的所有内容应用 using 声明,会有什么缺点?
注意:这是促使我提出这个问题的相关问题。
您能否举一个真实的例子,std::atomic::compare_exchange出于某种原因使用两个memory_order参数版本(因此一个memory_order参数版本不合适)?
看下面的例子(从这里获取):
class foo {
std::string my_str_;
public:
std::string_view get_str() const {
return my_str_.substr(1u);
}
};
Run Code Online (Sandbox Code Playgroud)
这段代码很糟糕,因为substr返回的是临时类std::string,所以返回的std::string_view对象是已经销毁的对象。但是,如果substr返回std::string_view,则此问题将不存在。
此外,对我来说,如果substr返回std::string_view而不是,这似乎是合乎逻辑的std::string,因为返回的字符串是字符串的视图,并且性能更高,因为没有进行复制。
如果substr返回,是否会有任何缺陷std::string_view(除了明显的缺陷:与C ++ 14失去一些兼容性-我并没有低估其重要性,我只是想知道是否存在其他缺陷)?
左移的结果可能是未定义的行为:
E1 << E2的值是E1左移E2位位置; 空位是零填充的.如果E1具有无符号类型,则结果的值为E1×2 ^ E2,比结果类型中可表示的最大值减少一个模数.否则,如果E1具有有符号类型和非负值,并且E1×2 ^ E2可在结果类型的相应无符号类型中表示,则转换为结果类型的该值是结果值; 否则,行为未定义.
右移的结果可以是实现定义的:
E1 >> E2的值是E1右移E2位位置.如果E1具有无符号类型或者E1具有有符号类型和非负值,则结果的值是E1/2 ^ E2的商的整数部分.如果E1具有带符号类型和负值,则结果值是实现定义的.
现在,我所知道的所有平台,未定义的行为/实现定义实际上在这里做了明智的事情:
所以,问题是,是否存在任何2补码平台/编译器,它们的行为不是这样的?
为什么这样问?大多数编译器不发射最佳代码(由phuclv提供的链接,之间检查出的拆卸test1和test2)为幂的2区在某些情况下(铛生成最佳代码,虽然).
对于某些类型,标准明确声明它们可以轻易复制.例如,std::chrono::day就是这种类型.
但是,因为std::string_view没有这样的说法.然而,它似乎满足了轻微可复制的要求(或者我可能忽略了某些东西?).
问题是,我可以指望这std::string_view是可以轻易复制的吗?
在开发大量浮点代码时,启用 FPU 异常非常有用。当运算结果为 NaN/inf 时,我们可以立即捕获它。
例如,在 Linux 上,我可以通过以下方式启用此功能:
feenableexcept(FE_DIVBYZERO|FE_INVALID|FE_OVERFLOW);
Run Code Online (Sandbox Code Playgroud)
在 SSE 出现之前,这种技术非常有效。然而,今天,对于 SSE,这与-ffast-math(或其他编译器的其他等效选项)发生冲突。
原因之一是 sqrt,因为 sqrt 是作为x*rsqrt(x). x当为零时,这会产生异常。当禁用异常时,这不是问题,因为 sqrt 函数可以处理此问题。
因此,我无法因此启用异常(也许还有其他原因)。
您有什么建议,如何在浮点错误发生的地方尽早捕获浮点错误(我不希望 NaN 传播,并且我也想捕获溢出到无穷大)(如果-ffast-math启用)?
看这个简单的概念示例:
template <typename T>
requires requires(T t) { { t+t } -> bool; }
void fn() {
}
int main() {
fn<bool>();
}
Run Code Online (Sandbox Code Playgroud)
在这里,我用bool作为type-constraint的return-type-requirement。目前的草案说:
类型约束:
嵌套名称说明符opt概念名称
嵌套名称说明符opt概念名称<template-argument-list opt>
所以type-constraint一定是一个concept-name。是否bool允许(或任何类型)作为概念名称?如果是,这意味着什么,标准草案在哪里允许?我认为这bool不是一个概念,所以这是不允许的。但是,gcc和clang都可以编译我的示例:Godbolt
(当然,允许类型是有道理的,我只是不知道标准在何处允许它,以及它的确切含义:类型是否应该完全匹配?否则会发生转换?)
注意:这是对以下问题的后续问题:当编译时已知的引用在结构中占用空间时,这是否是错过的优化?,这表明聚合初始化可以通过将其初始化b为a对其他变量的引用来代替作为引用的默认初始化。这个问题是关于不可能进行初始化的情况。
请参阅以下示例:
struct Foo {
int a;
int &b;
Foo() : b(a) { }
};
Run Code Online (Sandbox Code Playgroud)
如果错过了优化sizeof(Foo)!=sizeof(int)吗?
我的意思是,编译器可以b从其始终引用的结构中删除它a吗?
有什么阻止编译器进行这种转换的吗?
(请注意,struct Foo看起来是这样。没有其他构造函数,等等。但是您可以在周围添加任何内容Foo,这表明此优化将违反标准。)
我注意到 MSVC 的一个有趣行为:具有数组参数的函数与具有指针参数的函数的损坏方式不同。
void foo(double a[3]);
Run Code Online (Sandbox Code Playgroud)
被破坏为?foo@@YAXQEAN@Z. 如果我将参数类型分解回来,它就是double * const(这就是编译器抱怨的,godbolt)。另一方面,
void foo(double *a);
Run Code Online (Sandbox Code Playgroud)
被破坏为?foo@@YAXPEAN@Z,破坏后的参数类型为double *。请注意损坏名称中的Q/差异。P这不仅仅是表面上的差异,如果函数定义和声明在这方面不匹配,我们会收到链接器错误。
这种行为是否符合标准?甚至,顶级const修饰符对链接器有意义吗?这是什么意思?