C++ 迭代一项 - UB 或定义的行为
c++ iterate one item - UB or defined behaviour?
我最近一直在思考 c++ 中指针算术的规则,了解到指针算术只为指向数组中存在的对象的指针定义。
这让我怀疑以下代码的行为是否严格未根据标准定义。
谁能透露任何光芒?
#include <iostream>
#include <algorithm>
#include <iterator>
#include <utility>
#include <string>
#include <vector>
struct Thing {
std::string val;
};
int main() {
Thing a_thing;
std::vector<Thing> things;
// take address
auto first_thing = std::addressof(a_thing);
// take address of "one past the end" - UB?
auto last_thing = std::next(first_thing);
// copying exactly one item, but is it UB?
std::copy(first_thing, last_thing, std::back_inserter(things));
}
根据 5.7 [expr.add] 第 4 段,指向对象的指针的行为类似于单元素数组的第一个对象的指针:
出于这些运算符的目的,指向非数组对象的指针的行为与指向长度为 1 的数组的第一个元素的指针的行为相同,并将对象的类型作为其元素类型。
正如其他答案提到的,您的程序格式良好。以下是最新工作文件中的相关标准:
§5.7 (脚注 86) [补充]
为此目的,非数组元素的对象被视为属于单元素数组;请参阅 [expr.unary.op]。经过数组
x
n
元素的最后一个元素的指针被视为等效于指向为此目的x[n]
的假设元素的指针;参见[基本化合物]。
简而言之,非数组对象的行为类似于指针算术上下文中的单元素数组。因此,采用"一个过去"的地址是合法的。
这是
格式正确的。
[expr.add]/4 指出:
出于这些运算符的目的,指向非数组对象的指针的行为与指向长度为 1 的数组的第一个元素的指针的行为相同,并将对象的类型作为其元素类型。
之后声明([expr.add]/5):
如果指针操作数和结果都指向同一数组对象的元素,或者一个过去 数组对象的最后一个元素,求值不得产生溢出;否则,行为为 定义。
强调我的。
程序格式良好。
您可以设置一个指针超过数组的末尾,甚至刚好超出标量地址,就好像它是一个单元素数组一样。
第二部分在这里很重要。只要你实际上没有取消引用last_thing
,std::copy
不会,你的代码就会完美运行。
相关文章:
- 在提升multi_index容器中,是否定义了"default index"?
- #定义c-预处理器常量..我做错了什么
- 用C++中的一个变量定义一个常量
- 部分定义/别名模板模板参数
- C++映射:具有自定义类的运算符[]不起作用(总是返回0)
- #为""定义宏;静态";针对不同的上下文
- 如何确保C++函数在定义之前声明(如override关键字)
- 创建一个函数以在输入为负数或零时输出字符串.第一次执行用户定义的函数
- 当类在C++中定义时,有什么方法可以"register"类吗?
- 在命名空间中定义函数还是限定函数
- 此代码是否违反一个定义规则
- 编译C++时未定义的引用
- 不同翻译单元中不可重载的非内联函数定义
- 为什么在定义函数之前先声明它
- 'string.assign(string.data(), 5)' 是明确定义的还是 UB?
- c if语句:第一个条件取代第二个ub或定义良好
- C++ 迭代一项 - UB 或定义的行为
- 是a = 0;b =(a ,a 1);未定义的行为(UB)
- 将逐位移位运算符应用于有符号类型:UB和Impl.定义
- 未定义的行为-是用其他语言编写的函数,受C++关于UB的规则的约束