Mae*_*tro 5 c++ reference undefined-behavior c++17
您好,我有一个简单的问题:是否在同一个表达式中多次修改对象;一次通过其标识符(名称),第二次通过对它的引用或指向它的指针 未定义行为?
int i = 1;
std::cout << i << ", " << ++i << std::endl; //1- Error. Undefined Behavior
int& refI = i;
std::cout << i << ", " << ++refI << std::endl; //2- Is this OK?
int* ptrI = &refI; // ptrI point to the referred-to object (&i)
std::cout << i << ", " << ++*ptrI << std::endl; // 3 is this also OK?
Run Code Online (Sandbox Code Playgroud)
在第二个中,它似乎工作正常,但我对此感到困惑,因为从我所学到的;引用只是一个已经存在的对象的别名。并且对它的任何更改都会影响被引用的对象。因此,我在这里看到的是i和refI是相同的,因此在同i一个表达式中不止一次修改同一个对象 ( )。
但是为什么所有编译器都将语句 2 视为定义良好的行为?
语句 3 (ptrI) 怎么样?
它们在 C++17 之前都具有未定义的行为,并且自 C++17 以来都具有明确定义的行为。
请注意,在这两个示例中您都不会修改多次i。您仅用增量来修改它。
然而,对一个标量(这里是 的增量)产生副作用也是未定义的行为,而该标量i与值计算(这里是 的左侧使用i)不排序。副作用是通过直接作用于变量还是通过引用或指针产生并不重要。
在 C++17 之前,<<运算符并不暗示其操作数的任何排序,因此所有示例中的行为均未定义。
从 C++17 开始,<<运算符保证从左到右计算其操作数。C++17 还将运算符的排序规则扩展到使用运算符表示法调用时的重载运算符。因此,在所有示例中,行为都是明确定义的,并且首先i评估左侧的使用,然后递增之前的值。i
但请注意,某些编译器没有非常及时地对评估规则实施这些更改,因此即使您使用该-std=c++17标志,它仍然可能不幸地违反旧版和当前编译器版本的预期行为。
此外,至少在 GCC 的情况下,-Wsequence-point警告被明确记录为即使对于 C++17 中明确定义的行为也发出警告,以帮助用户避免编写在 C 和早期 C++ 中具有未定义行为的代码版本,请参阅GCC 文档。
编译器不需要(也不能够)诊断所有未定义行为的情况。在某些简单的情况下,它将能够向您发出警告(您可以使用-Werror或类似的方法将其转变为错误),但在更复杂的情况下,它不会。尽管如此,如果您有未定义的行为,无论是否已诊断,您的程序都会失去对其行为的任何保证。
| 归档时间: |
|
| 查看次数: |
112 次 |
| 最近记录: |