首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >指针/整数算法(Un)定义的行为

指针/整数算法(Un)定义的行为
EN

Stack Overflow用户
提问于 2014-08-12 13:39:58
回答 1查看 481关注 0票数 6

我有以下函数模板:

代码语言:javascript
复制
template <class MostDerived, class HeldAs>
HeldAs* duplicate(MostDerived *original, HeldAs *held)
{
  // error checking omitted for brevity
  MostDerived *copy = new MostDerived(*original);
  std::uintptr_t distance = reinterpret_cast<std::uintptr_t>(held) - reinterpret_cast<std::uintptr_t>(original);
  HeldAs *copyHeld = reinterpret_cast<HeldAs*>(reinterpret_cast<std::uintptr_t>(copy) + distance);
  return copyHeld;
}

其目的是复制特定类型的对象,并将其“持有”返回给与输入相同的子对象。请注意,原则上,HeldAs可以是MostDerived的一个模棱两可或不可访问的基类,所以这里没有强制转换可以帮助您。

这是我的代码,但它可以用于我无法控制的类型(即我不能修改MostDerivedHeldAs)。该职能有以下先决条件:

  • *original是动态类型的MostDerived
  • HeldAsMostDerivedMostDerived的直接或间接基类(忽略cv-限定)。
  • *held指的是*original或它的基类子对象之一。

让我们假设先决条件已经满足了。在这种情况下,duplicate是否有明确的行为?

C++11 expr.reinterpret.cast说(大胆强调我的观点):

4指针可以显式转换为任何足以容纳指针的整型。映射函数是实现定义的。注意:对于那些知道底层机器的寻址结构的人来说,这并不令人惊讶。-end笔记..。 5积分类型或枚举类型的值可以显式转换为指针。一个指针转换成一个足够大小的整数(如果在实现中存在这样的话),并返回到相同的指针类型,它将有它的原始值;指针和整数之间的映射是实现定义的。注意:除3.7.4.3中描述的情况外,这种转换的结果将不是安全派生的指针值。-end注记

好吧,假设我的编译器是GCC (或者说Clang,因为它使用GCC对实现定义的行为的定义)。引用GCC博士第五章关于C++实现的定义行为:

..。C语言的相应文档中记录了一些选择。见C执行情况。..。

关于第4.7章 (C实现、数组和指针):

将指针转换为整数的结果,反之亦然(C90 6.3.4、C99和C11 6.3.2.3)。 从指针到整数的转换将丢弃大多数重要位(如果指针表示大于整数类型),如果指针表示小于整数类型,则扩展符号,否则比特将保持不变。 从整数到指针的转换如果指针表示小于整数类型,则丢弃最重要的位;如果指针表示大于整数类型,则根据整数类型的签名性进行扩展,否则比特不变。

到现在为止还好。看来,由于我使用的std::uintptr_t保证足够大,可以用于任何指针,而且由于我处理的是相同的类型,所以copyHeld应该指向与held*original中指向的相同的*copy子对象。

不幸的是,GCC的文档中还有一个段落:

当再次将指针转换为整数和返回时,结果指针必须引用与原始指针相同的对象,否则行为将不定义。也就是说,不能使用整数算法来避免C99和C11 6.5.6/8中禁止的指针算术的未定义行为。

沃姆。因此,现在看来,尽管copyHeld的值是按照前两段的规则计算的,但第三段仍然将其发送到未定义的行为域。

我基本上有三个问题:

  1. 我的阅读是否正确,duplicate的行为是否未定义?
  2. 这是哪种不明确的行为?“形式上不确定,但无论如何都会做你想做的”那类,还是“期望随机的碰撞和/或自发的自焚”?
  3. 如果它确实是未定义的,那么是否有一种方法可以以一种定义良好(可能依赖编译器)的方式来完成这样的事情?

虽然我的问题仅限于GCC (和Clang)在编译器方面的行为,但我希望得到一个考虑各种HW平台的答案,从普通的桌面到异国风格的桌面。

EN

回答 1

Stack Overflow用户

发布于 2014-08-12 23:33:47

通常的模式是在基类中放置一个clone()

然后,每个派生类都可以实现自己版本的克隆。

代码语言:javascript
复制
class Base
{
     public:
        virtual Base*  clone() = 0;
};

class D: public Base
{
        virtual Base*  clone(){  return new D(*this);}
};
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25265824

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档