小编Rus*_*lan的帖子

为什么C++编译器不优化这个条件布尔赋值作为无条件赋值?

考虑以下功能:

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在阅读它的点不未定义行为的价值,但我不知道这是否是可能的.

c++ optimization

116
推荐指数
3
解决办法
6923
查看次数

使用以前的函数参数来声明新函数是否合法?

以下代码与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扩展?

c++ gcc function language-lawyer

35
推荐指数
3
解决办法
1441
查看次数

const_iterator与迭代器的比较是否定义明确?

请考虑以下代码:

#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一样有效.但根据标准,它实际上是否定义明确?能iteratorconst_iterator安全地进行比较?

c++ iterator const-iterator comparison-operators

30
推荐指数
3
解决办法
2635
查看次数

铸造到'void'真的有什么作用?

经常使用的语句(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;.

哪一项更正确?如果没有,那么如何解释编译器警告的差异?

c++ casting void compiler-warnings suppress-warnings

29
推荐指数
3
解决办法
1万
查看次数

初始化nullptr_t时,0如何区别于其他整数?

按照我的理解,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)

这是如何运作的?即如何在标准库区分05在编译的时候,如果这些文字是不是模板参数?

可以创建一个自定义类,它在编译时类似地区分其构造函数的参数,而不是std::nullptr_t用于此吗?

c++ types type-conversion

20
推荐指数
3
解决办法
1139
查看次数

初始化表达式可以使用变量本身吗?

请考虑以下代码:

#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或在其他情况下,行为是否会变得不确定?

c++ initialization undefined-behavior language-lawyer

17
推荐指数
2
解决办法
945
查看次数

装配ADC(随附进位)到C++

有汇编指令ADC.我发现这意味着"随身携带".但我不知道意味着什么.或者如何用C++编写这个指令.我知道它不一样ADD.所以做一个简单的求和是不正确的.

信息:
在Windows中编译.我正在使用32位Windows安装.我的处理器是Intel的Core 2 Duo.

c++ x86 assembly

16
推荐指数
5
解决办法
3万
查看次数

如何实现没有未定义行为的快速逆sqrt?

根据我对严格别名规则的理解,这个快速反平方根的代码将导致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位格式, …

c++ strict-aliasing undefined-behavior

15
推荐指数
2
解决办法
1496
查看次数

intN_t溢出是否定义明确?

在C99中,有一些(可选的)类型int8_t,int16_t例如,它们保证具有精确指定的宽度和没有填充位,并且表示二进制补码(7.18.1.1)中的数字.在6.2.6.2中,有符号整数溢出被提及为脚注44)和45),即它可能导致在填充位中捕获值.

由于intN_t没有任何填充位,并且它们保证是两个补码,这是否意味着它们的溢出不会产生任何未定义的行为?什么是例如溢出乘法的结果?添加怎么样?2^N对于无符号类型,结果是否减少了模数?

c int integer-overflow undefined-behavior

15
推荐指数
1
解决办法
292
查看次数

这个内联初始化std :: array有什么问题?

请考虑以下声明:

#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)

为什么我不能在结构定义中使用单括号的简单初始化?

c++ arrays g++ c++11

12
推荐指数
1
解决办法
5712
查看次数