对某些函数使用增量运算符
Using increment operators with some functions
如果我做这样的事情:
static int counter = 0;
counter = std::min(8, counter++);
我收到 g++ 的警告说:
operation on 'counter' may be undefined [-Wsequence-point]
这工作正常:
static int counter = 0;
counter++;
counter = std::min(8, counter);
结果与++counter
和/或std::max
相同。
我无法弄清楚第一个版本有什么问题。std::max 也会发生这种情况。仅举个例子,我在使用 GLM 的函数时没有收到任何警告。
谁能为我解释一下?我在 Ubuntu 4.8 上使用 GCC 14.04。
编辑:更多的测试(我应该先做)如果我做cntr = std::min(8, ++cntr);
,就像我在实际应用程序中一样,打印此行之后的值会导致 1,然后是 2,然后是 3,依此类推,但是,如果我cntr = std::min(8, cntr++);
,则每次的 vaule 都是 0,它永远不会增加。
我认为迈克·西摩的评论是正确的 - 不应该有 UB,因为函数参数表达式应该在函数调用之前排序。从 1.19/15:
调用函数(无论该函数是否为内联函数)时,与任何参数表达式或指定被调用函数的后缀表达式关联的每个值计算和副作用都会在执行被调用函数主体中的每个表达式或语句之前进行排序。
所以 gcc 可能是不正确的。另请注意,在其他一些情况下,警告不会显示:
int f(int a, int b);
template <typename T> T g(T a, T b);
template <typename T> const T& h(const T& a, const T& b);
counter = f(8, counter++); // no warning
counter = g(8, counter++); // no warning
counter = h(8, counter++); // gcc gives warning - there should be nothing special
// about h as compared to f,g... so warning is likely
// incorrect
Clang没有对这些警告。
鉴于函数参数在调用之前是有序的,这就解释了为什么:
int counter = 0;
counter = std::min(8, counter++);
始终返回 0。该代码等效于:
counter = 0;
int a1 = 8; // these two can be evaluated in either order
int a2 = counter++; // either way, a2 == 0, counter == 1
counter = std::min(a1, a2); // which is min(8, 0) == 0.
相关文章:
- 为什么将值返回函数传递给重载=运算符对运算符函数有效,而对其他运算符无效
- 在 C++ 中调用类中的运算符函数
- 错误 C2676:std::set::const_iterator 没有运算符 + 函数?
- 为什么 ADL 的运算符函数行为与其他函数不同?
- 将内置类型变量传递给只有一个类类型参数的"+"运算符函数时自动类型转换的构造函数
- 第二个常量在运算符函数中做什么?
- 重载赋值运算符函数和复制构造函数中的错误
- 内置类型的运算符函数
- 如何调用运算符函数添加两个对象?
- Const 仍然允许在运算符函数 c++ 下进行更改
- 在呼叫运算符函数const中调用运算符时错误
- 是否有一种方法可以在超载运算符函数中接触默认运算符函数
- 重载时获取堆栈溢出 >> 运算符函数是为类调用的。我需要进行哪些更改?
- 运算符 [] 函数的实现是如何工作的
- C++:使用父类运算符函数更新子类对象的继承变量
- 创建一个接受 2 个输入参数的文本运算符函数
- 为什么找不到重载运算符函数?
- 为什么auto_ptr中有模板复制构造函数和覆盖运算符函数
- 为什么某些C++标准库“运算符<<”函数将其流宽度重置为 0
- C++SFINAE运算符/函数结果类型检查