考虑以下功能:
void func(bool& flag)
{
if(!flag) flag=true;
}
Run Code Online (Sandbox Code Playgroud)
在我看来,如果flag有一个有效的布尔值,这相当于无条件设置它true,如下所示:
void func(bool& flag)
{
flag=true;
}
Run Code Online (Sandbox Code Playgroud)
然而,gcc和clang都没有这样优化它 - 都在-O3优化级别生成以下内容:
_Z4funcRb:
.LFB0:
.cfi_startproc
cmp BYTE PTR [rdi], 0
jne .L1
mov BYTE PTR [rdi], 1
.L1:
rep ret
Run Code Online (Sandbox Code Playgroud)
我的问题是:只是代码太特殊flag而不关心优化,或者是否有任何好的理由为什么这样的优化是不希望的,因为它不是一个参考volatile?看来这可能是唯一的原因是,flag可以在某种程度上具有非true-或- false在阅读它的点不未定义行为的价值,但我不知道这是否是可能的.
以下代码与GCC完全编译:
void func(int arg1, decltype(arg1) arg2)
{
(void)arg2;
}
int main(){}
Run Code Online (Sandbox Code Playgroud)
我用这个命令编译:
g++ -std=c++14 test.cpp -o test -pedantic-errors -Wall -Wextra
Run Code Online (Sandbox Code Playgroud)
但是在函数声明中间使用参数似乎很奇怪.它在标准C++中实际有效,还是GCC扩展?
请考虑以下代码:
#include <vector>
#include <iostream>
int main()
{
std::vector<int> vec{1,2,3,5};
for(auto it=vec.cbegin();it!=vec.cend();++it)
{
std::cout << *it;
// A typo: end instead of cend
if(next(it)!=vec.end()) std::cout << ",";
}
std::cout << "\n";
}
Run Code Online (Sandbox Code Playgroud)
在这里我介绍了一个错字:在比较中我打电话vec.end()而不是vec.cend().这似乎与gcc 5.2一样有效.但根据标准,它实际上是否定义明确?能iterator和const_iterator安全地进行比较?
经常使用的语句(void)x;允许禁止有关未使用变量的警告x.但是如果我尝试编译以下内容,我会得到一些我不太了解的结果:
int main()
{
int x;
(short)x;
(void)x;
(int)x;
}
Run Code Online (Sandbox Code Playgroud)
用g ++编译它,我得到以下警告:
$ g++ test.cpp -Wall -Wextra -o test
test.cpp: In function ‘int main()’:
test.cpp:4:13: warning: statement has no effect [-Wunused-value]
(short)x;
^
test.cpp:6:11: warning: statement has no effect [-Wunused-value]
(int)x;
^
Run Code Online (Sandbox Code Playgroud)
因此,我得出结论,转换为void与任何其他类型的转换非常不同,是目标类型相同decltype(x)或不同的东西.我猜测可能的解释是:
(void)x;但其他演员不会抑制警告.所有陈述同样没有任何效果.void x;并非如此short x;.哪一项更正确?如果没有,那么如何解释编译器警告的差异?
按照我的理解,std::nullptr_t可以从被初始化nullptr,以及从0.但同时下面的第三次初始化不起作用,尽管5类型如下0:
#include <memory>
int main()
{
std::nullptr_t null1=0;
std::nullptr_t null2=nullptr;
std::nullptr_t null3=5; // error: cannot convert ‘int’ to ‘std::nullptr_t’ in initialization
}
Run Code Online (Sandbox Code Playgroud)
这是如何运作的?即如何在标准库区分0从5在编译的时候,如果这些文字是不是模板参数?
可以创建一个自定义类,它在编译时类似地区分其构造函数的参数,而不是std::nullptr_t用于此吗?
请考虑以下代码:
#include <iostream>
struct Data
{
int x, y;
};
Data fill(Data& data)
{
data.x=3;
data.y=6;
return data;
}
int main()
{
Data d=fill(d);
std::cout << "x=" << d.x << ", y=" << d.y << "\n";
}
Run Code Online (Sandbox Code Playgroud)
这d是从返回值复制初始化的fill(),但在返回结果之前fill()写入d自身.我关心的是d在初始化之前非常简单地使用它,并且在一些(所有?)情况下使用未初始化的变量会导致不确定的行为.
那么这段代码是有效的,还是有未定义的行为?如果它有效,一旦Data停止POD或在其他情况下,行为是否会变得不确定?
有汇编指令ADC.我发现这意味着"随身携带".但我不知道这意味着什么.或者如何用C++编写这个指令.我知道它不一样ADD.所以做一个简单的求和是不正确的.
信息:
在Windows中编译.我正在使用32位Windows安装.我的处理器是Intel的Core 2 Duo.
根据我对严格别名规则的理解,这个快速反平方根的代码将导致C++中未定义的行为:
float Q_rsqrt( float number )
{
long i;
float x2, y;
const float threehalfs = 1.5F;
x2 = number * 0.5F;
y = number;
i = * ( long * ) &y; // type punning
i = 0x5f3759df - ( i >> 1 );
y = * ( float * ) &i;
y = y * ( threehalfs - ( x2 * y * y ) );
return y;
}
Run Code Online (Sandbox Code Playgroud)
这段代码确实会导致UB吗?如果是,如何以符合标准的方式重新实现?如果没有,为什么不呢?
假设:在调用此函数之前,我们已经以某种方式检查了浮点数是IEEE 754 32位格式, …
在C99中,有一些(可选的)类型int8_t,int16_t例如,它们保证具有精确指定的宽度和没有填充位,并且表示二进制补码(7.18.1.1)中的数字.在6.2.6.2中,有符号整数溢出被提及为脚注44)和45),即它可能导致在填充位中捕获值.
由于intN_t没有任何填充位,并且它们保证是两个补码,这是否意味着它们的溢出不会产生任何未定义的行为?什么是例如溢出乘法的结果?添加怎么样?2^N对于无符号类型,结果是否减少了模数?
请考虑以下声明:
#include <array>
struct X
{
//std::array<bool,3> arr={false,false,false};
bool brr[3]={false,false,false};
};
Run Code Online (Sandbox Code Playgroud)
按原样,它通常由g ++ 5.2编译.但如果我取消注释std::array,我会收到一个错误:
test.cpp:5:46: error: array must be initialized with a brace-enclosed initializer
std::array<bool,3> arr={false,false,false};
^
test.cpp:5:46: error: too many initializers for ‘std::array<bool, 3u>’
Run Code Online (Sandbox Code Playgroud)
OTOH,这个声明里面没有问题main().此外,以下初始化在内部工作struct X:
std::array<bool,3> arr={{false,false,false}};
Run Code Online (Sandbox Code Playgroud)
为什么我不能在结构定义中使用单括号的简单初始化?