小编gez*_*eza的帖子

是否允许这种浮点优化?

我试图检查哪里float失去了精确表示大整数的能力。所以我写了这个小片段:

int main() {
    for (int i=0; ; i++) {
        if ((float)i!=i) {
            return i;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

该代码似乎适用于所有编译器,但不包括clang。Clang生成一个简单的无限循环。上帝保佑

可以吗?如果是,那是QoI问题吗?

c++ floating-point clang

88
推荐指数
2
解决办法
3236
查看次数

是否允许编译器优化本地volatile变量?

是否允许编译器对此进行优化(根据C++ 17标准):

int fn() {
    volatile int x = 0;
    return x;
}
Run Code Online (Sandbox Code Playgroud)

这个?

int fn() {
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

如果是,为什么?如果没有,为什么不呢?


这里有一些关于这个主题的思考:当前编译器编译fn()为放在堆栈上的局部变量,然后返回它.例如,在x86-64上,gcc创建了这个:

mov    DWORD PTR [rsp-0x4],0x0 // this is x
mov    eax,DWORD PTR [rsp-0x4] // eax is the return register
ret    
Run Code Online (Sandbox Code Playgroud)

现在,据我所知,标准并没有说应该将一个局部volatile变量放在堆栈上.所以,这个版本同样好:

mov    edx,0x0 // this is x
mov    eax,edx // eax is the return
ret    
Run Code Online (Sandbox Code Playgroud)

这里,edx商店x.但是现在,为什么要停在这里?由于edxeax均为零,我们可以只说:

xor    eax,eax // eax is the return, and x as well
ret    
Run Code Online (Sandbox Code Playgroud)

我们转变 …

c++ volatile language-lawyer c++17

75
推荐指数
5
解决办法
5748
查看次数

std :: tuple sizeof,是否错过了优化?

我已经检查了所有主要的编译器,sizeof(std::tuple<int, char, int, char>)所有这些都是16。大概它们只是将元素按顺序放入元组,因此由于对齐而浪费了一些空间。

如果元组在内部像这样存储元素:int, int, char, char,则其sizeof可能为12。

实现有可能执行此操作,还是该标准中的某些规则禁止这样做?

c++ tuples padding language-lawyer

69
推荐指数
2
解决办法
2765
查看次数

std :: memcpy是否在不同的可复制类型之间是未定义的行为?

我一直在std::memcpy用来规避严格的混叠很长一段时间.

例如,检查a float,像这样:

float f = ...;
uint32_t i;
static_assert(sizeof(f)==sizeof(i));
std::memcpy(&i, &f, sizeof(i));
// use i to extract f's sign, exponent & significand
Run Code Online (Sandbox Code Playgroud)

但是,这次,我检查了标准,我还没有找到任何可以验证这一点的东西.我所发现的是这个:

对于平凡可复制类型T的任何对象(可能重叠的子对象除外),无论对象是否保持类型T的有效值,组成对象的基础字节([intro.memory])都可以复制到char,unsigned char或std :: byte([cstddef.syn])数组.40如果将该数组的内容复制回对象,则该对象应随后保持其原始值.[例如:

#define N sizeof(T)
char buf[N];
T obj;                          // obj initialized to its original value
std::memcpy(buf, &obj, N);      // between these two calls to std?::?memcpy, obj might be modified
std::memcpy(&obj, buf, N);      // at this point, each subobject of obj of scalar …
Run Code Online (Sandbox Code Playgroud)

c++ strict-aliasing undefined-behavior language-lawyer c++17

52
推荐指数
3
解决办法
2898
查看次数

是否有可能通过指向另一个未释放子对象的指针来获得一个子对象的指针?

看下面这个简单的代码:

struct Point {
    int x;
    int y;
};

void something(int *);

int main() {
    Point p{1, 2};

    something(&p.x);

    return p.y;
}
Run Code Online (Sandbox Code Playgroud)

我希望main可以将返回值优化为return 2;,因为something它无法访问p.y,只能返回的指针p.x

但是,没有一个主要的编译器会优化mainto 的返回值2上帝保佑

如果仅允许访问,标准中是否存在可以something修改的内容?如果是,这是否取决于标准布局?p.yp.xPoint

如果我使用something(&p.y);,该return p.x;怎么办?

c++ pointers offsetof language-lawyer c++17

51
推荐指数
1
解决办法
1397
查看次数

浮点平等

众所周知,在比较浮点值时必须小心.通常,==我们使用一些基于epsilon或ULP的相等测试来代替使用.

但是,我想知道,有什么案例,使用时==完全没问题吗?

看看这个简单的片段,哪些案例可以保证成功?

void fn(float a, float b) {
    float l1 = a/b;
    float l2 = a/b;

    if (l1==l1) { }        // case a)
    if (l1==l2) { }        // case b)
    if (l1==a/b) { }       // case c)
    if (l1==5.0f/3.0f) { } // case d)
}

int main() {
    fn(5.0f, 3.0f);
}
Run Code Online (Sandbox Code Playgroud)

注意:我已经检查了这个这个,但它们不包括(全部)我的情况.

注2:似乎我必须添加一些加号信息,所以答案在实践中很有用:我想知道:

  • C++标准说的是什么
  • 如果C++实现遵循IEEE-754会发生什么

这是我在目前的标准草案中找到的唯一相关陈述:

浮点类型的值表示是实现定义的.[注意:本文档对浮点运算的准确性没有要求; 另见[support.limits]. - 结束说明]

那么,这是否意味着甚至"案例a)"是实现定义的?我的意思是,l1==l1绝对是一个浮点运算.那么,如果一个实现是"不准确的",那么可能l1==l1是假的?


我认为这个问题不是重复的浮点数==永远好吗?.这个问题没有解决我提出的任何案件.同一主题,不同的问题.我想特别针对案例a)-d)得到答案,因为我无法在重复的问题中找到答案.

c++ floating-point precision language-lawyer floating-point-comparison

46
推荐指数
3
解决办法
3391
查看次数

如何使用标准库迭代相等的值?

假设我有一个向量:

std::vector<Foo> v;
Run Code Online (Sandbox Code Playgroud)

此向量已排序,因此相等的元素彼此相邻。

获得所有表示具有相等元素的范围的迭代器对的最佳方法是什么(使用标准库)?

while (v-is-not-processed) {
    iterator b = <begin-of-next-range-of-equal-elements>;
    iterator e = <end-of-next-range-of-equal-elements>;

    for (iterator i=b; i!=e; ++i) {
        // Do something with i
    }
}
Run Code Online (Sandbox Code Playgroud)

我想知道如何在上面的代码中获取b和的值e

因此,例如,如果v包含以下数字:

 index 0 1 2 3 4 5 6 7 8 9
 value 2 2 2 4 6 6 7 7 7 8
Run Code Online (Sandbox Code Playgroud)

然后,我想在循环中具有be指向元素:

 iteration  b  e
 1st        0  3
 2nd        3  4
 3rd        4  6
 4th        6  9
 5th …
Run Code Online (Sandbox Code Playgroud)

c++ algorithm c++-standard-library iterator-range c++17

39
推荐指数
5
解决办法
1827
查看次数

是否允许删除修改其参数?

在答案/sf/answers/49319791/中,引用了Stroustrup:

C++显然允许delete的实现将左值操作数归零,我曾希望实现会这样做,但这个想法似乎并没有受到实现者的欢迎.

但是,我没有在标准中找到这个明确的陈述.目前的标准草案(N4659)中有一部分可以用这种方式解释:

6.7:

当达到存储区域的持续时间结束时,表示该存储区域的任何部分的地址的所有指针的值变为无效指针值(6.9.2).通过无效指针值间接并将无效指针值传递给释放函数具有未定义的行为.对无效指针值的任何其他使用都具有实现定义的行为.

脚注:某些实现可能会定义复制无效指针值会导致系统生成的运行时错误

因此,在a之后delete ptr;,ptrs值变为无效指针值,并且使用此值具有实现定义的行为.但是,它并没有说ptr允许改变价值.

这可能是一个哲学问题,如果一个人不能使用它的价值,怎么能决定一个价值发生了变化呢?

6.9:

对于普通可复制类型T的任何对象(基类子对象除外),无论对象是否保持类型T的有效值,构成对象的基础字节(4.4)都可以复制到char数组中, unsigned char,或std :: byte(21.2.1).43如果将该数组的内容复制回对象,该对象应随后保持其原始值.

所以,似乎它对memcpy一个char数组的无效指针值是有效的(取决于哪个语句是"更强",6.7或6.9.对我来说,6.9似乎更强).

这样,我可以通过以下方式检测到指针值已被改变delete:memcpy指向deleteto char数组之前和之后的值,然后比较它们.

所以,据我所知,6.7 delete不允许允许修改其参数.

是否允许删除修改其参数?

看看这里的评论:https: //stackoverflow.com/a/45142972/8157187


这是一个不太可能但仍然可能的现实世界代码,其中重要的是:

SomeObject *o = ...; // We have a SomeObject
// This SomeObject is registered into someHashtable, with its memory address
// The hashtable interface is C-like, it handles opaque keys (variable length unsigned char arrays)

delete o; …
Run Code Online (Sandbox Code Playgroud)

c++ language-lawyer c++17

36
推荐指数
1
解决办法
910
查看次数

标准为何不将模板构造函数视为副本构造函数?

这是复制构造函数[class.copy.ctor / 1]的定义

如果类X的非模板构造函数的第一个参数为X&,const X&,volatile X&或const volatile X&类型,并且没有其他参数,或者所有其他参数都具有默认参数([dcl。 fct.default])。

为什么标准将模板排除为复制构造函数?

在这个简单的示例中,两个构造函数都是副本构造函数:

struct Foo {
    Foo(const Foo &); // copy constructor
    Foo(Foo &);       // copy constructor
};
Run Code Online (Sandbox Code Playgroud)

参见以下类似示例:

struct Foo {
     Foo() = default;

     template <typename T>
     Foo(T &) {
         printf("here\n");
     }
};

int main() {
    Foo a;
    Foo b = a;
}
Run Code Online (Sandbox Code Playgroud)

在此示例中,here将被打印。因此,似乎我的模板构造函数是一个复制构造函数,至少它的行为类似于一个(在通常调用复制构造函数的上下文中被调用)。

为什么文本中存在“非模板”要求?

c++ templates constructor copy-constructor language-lawyer

32
推荐指数
2
解决办法
1757
查看次数

当编译时已知的引用占用结构中的空间时,是否错过了优化?

请参阅以下示例:

struct Foo {
    int a;
    int &b = a;
};
Run Code Online (Sandbox Code Playgroud)

如果错过了优化sizeof(Foo)!=sizeof(int)吗?

我的意思是,编译器可以b从其始终引用的结构中删除它a吗?

有什么阻止编译器进行这种转换的吗?

(请注意,struct Foo看起来是这样。没有构造函数,等等。但是您可以在周围添加任何内容Foo,这表明该优化将违反标准。)

c++ struct initialization reference language-lawyer

27
推荐指数
1
解决办法
1093
查看次数