- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
(这是关于未定义行为 (UB) 的另一个问题。如果这段代码在某些编译器上“有效”,那么这在 UB 领域就没有任何意义。这是可以理解的。但是我们到底在下面的哪一行跨入 UB?)
(关于 SO 已经有很多非常相似的问题,例如 (1) 但我很好奇在取消引用指针之前可以安全地使用指针做什么。)
从一个非常简单的基类开始。没有 virtual
方法。无继承。 (也许这可以扩展到任何 POD?)
struct Base {
int first;
double second;
};
然后是添加(非 virtual
)方法但不添加任何成员的简单扩展。没有 virtual
继承。
struct Derived : public Base {
int foo() { return first; }
int bar() { return second; }
};
然后,考虑以下几行。如果与定义的行为有一些偏差,我很想知道到底是哪一行。我的猜测是我们可以安全地对指针执行大部分计算。这些指针计算中的一些,如果没有完全定义,是否有可能至少给我们某种并非完全无用的“不确定/未指定/实现定义”的值?
void foo () {
Base b;
void * vp = &b; // (1) Defined behaviour?
cout << vp << endl; // (2) I hope this isn't a 'trap value'
cout << &b << endl; // (3a) Prints the same as the last line?
// (3b) It has the 'same value' in some sense?
Derived *dp = (Derived*)(vp);
// (4) Maybe this is an 'indeterminate value',
// but not fully UB?
cout << dp << endl; // (5) Defined behaviour also? Should print the same value as &b
编辑:如果节目到这里结束,会是UB吗?请注意,在这个阶段,我没有尝试对 dp
做任何事情。 ,而不是将指针本身打印到输出。如果简单的转换是 UB,那么我想问题到此结束。
// I hope the dp pointer still has a value,
// even if we can't dereference it
if(dp == &b) { // (6) True?
cout << "They have the same value. (Whatever that means!)" << endl;
}
cout << &(b.second) << endl; (7) this is definitely OK
cout << &(dp->second) << endl; // (8) Just taking the address. Is this OK?
if( &(dp->second) == &(b.second) ) { // (9) True?
cout << "The members are stored in the same place?" << endl;
}
}
我对上面的(4) 有点紧张。但我认为转换到 void 指针和从 void 指针转换总是安全的。也许可以讨论这样一个指针的值。但是,它是否被定义为进行转换,并打印指向 cout
的指针? ?
(6) 也很重要。这会评估为真吗?
在 (8) 中,我们第一次取消引用此指针(正确的术语?)。但请注意,这一行不是从 dp->second
读取的。 .它仍然只是一个左值,我们获取它的地址。我假设这种地址计算是由我们从 C 语言获得的简单指针算术规则定义的?
如果以上都OK,或许我们可以证明static_cast<Derived&>(b)
没问题,并且会导致一个完美可用的对象。
最佳答案
void *
始终保证工作,并且指针保证在往返过程中存活 Base *
-> void *
-> Base *
(C++11 §5.2.9 ¶13);vp
是一个有效的指针,所以应该没有任何问题。一个。尽管打印指针是实现定义的1,打印的值应该是相同的:事实上operator<<
默认情况下仅为 const void *
重载, 所以当你写 cout<<&b
您正在转换为 const void *
无论如何,即什么 operator<<
在这两种情况下都看到了 &b
转换到 const void *
.
是的,如果我们采用“具有相同值”的唯一合理定义 - 即它与 ==
比较相等运算符(operator);事实上,如果你比较vp
和 &b
与 ==
, 结果是 true
, 如果你转换 vp
至 Base *
(由于我们在 1 中所说的),如果你转换 &b
至 void *
.
这两个结论都来自 §4.10 ¶2,其中指定任何指针都可以转换为 void *
(取模通常的 cv 限定的东西),结果«指向对象 [...] 所在的存储位置的开始»1
这很棘手; C 风格的转换相当于 static_cast
, 这将很高兴地允许将 «"pointer to cv1 B
[...] 转换到 [...] "pointer to *cv2 D
",其中 D
是从 B
派生的类 »(§5.2.9,¶11;有一些额外的约束,但它们在这里得到满足);但是:
If the prvalue of type “pointer to cv1
B
” points to aB
that is actually a subobject of an object of typeD
, the resulting pointer points to the enclosing object of typeD
. Otherwise, the result of the cast is undefined.
(强调)
因此,这里允许您进行强制转换,但结果未定义...
... 引导我们打印它的值;由于转换的结果未定义,您可能会得到任何东西。由于指针可能被允许具有陷阱表示(至少在 C99 中,我只能在 C++11 标准中找到对“陷阱”的稀疏引用,但我认为这种行为可能应该已经从 C89 继承)你甚至可以只需读取 这个指针并通过 operator<<
打印它就会崩溃.
如果遵循,则 6、8 和 9 也没有意义,因为您使用的是未定义的结果。
此外,即使转换有效,严格的别名(§3.10,¶10)也会阻止你对指向的对象做任何有意义的事情,因为别名是 Base
通过 Derived
对象仅当 Base
的动态类型时才允许使用指针对象实际上是 Derived
;任何偏离 §3.10 ¶10 中指定的异常的行为都会导致未定义的行为。
注释:
operator>>
代表num_put
在概念上委托(delegate)给 printf
与 %p
,其描述归结为“定义的实现”。
这排除了我的担心,即在转换为 void *
时,邪恶的实现在理论上可能会返回不同但等效的值。 .
关于c++ - 如果 Derived 不向 Base 添加新成员(并且是 POD),那么可以安全地完成什么样的指针转换和取消引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19741843/
我创建了一个用户可以添加测试的字段。这一切运行顺利我只希望当用户点击(添加另一个测试)然后上一个(添加另一个测试)删除并且这个显示在新字段中。 所有运行良好的唯一问题是点击(添加另一个字段)之前添加另
String[] option = {"Adlawan", "Angeles", "Arreza", "Benenoso", "Bermas", "Brebant
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 这个问题似乎不是关于 a specific programming problem, a softwar
我正在努力将 jQuery 滚动功能添加到 nav-tab (Bootstrap 3)。我希望用户能够选择他们想要的选项卡,并在选项卡内容中有一个可以平滑滚动到 anchor 的链接。这是我的代码,可
我正在尝试在用户登录后再添加 2 个 ui 选项卡。首先,我尝试做一个之后。 $('#slideshow').tabs('remove', '4'); $("#slideshow ul li:last
我有一个包含选择元素的表单,我想通过选择添加和删除其中一些元素。这是html代码(这里也有jsfiddle http://jsfiddle.net/txhajy2w/):
正在写这个: view.backgroundColor = UIColor.white.withAlphaComponent(0.9) 等同于: view.backgroundColor = UICo
好的,如果其中有任何信息,我想将这些列添加到一起。所以说我有 账户 1 2 3 . 有 4 个帐户空间,但只有 3 个帐户。我如何创建 java 脚本来添加它。 最佳答案 Live Example H
我想知道是否有一种有效的预制算法来确定一组数字的和/差是否可以等于不同的数字。示例: 5、8、10、2,使用 + 或 - 等于 9。5 - 8 = -3 + 10 = 7 + 2 = 9 如果有一个预
我似乎有一个卡住的 git repo。它卡在所有基本的添加、提交命令上,git push 返回所有内容为最新的。 从其他帖子我已经完成了 git gc 和 git fsck/ 我认为基本的调试步骤是
我的 Oracle SQL 查询如下- Q1- select hca.account_number, hca.attribute3, SUM(rcl.extended_amou
我正在阅读 http://developer.apple.com/iphone/library/documentation/iPhone/Conceptual/iPhoneOSProgrammingG
我正在尝试添加一个“加载更多”按钮并限制下面的结果,这样投资组合页面中就不会同时加载 1000 个内容,如下所示:http://typesetdesign.com/portfolio/ 我对 PHP
我遇到这个问题,我添加了 8 个文本框,它工作正常,但是当我添加更多文本框(如 16 个文本框)时,它不会添加最后一个文本框。有人遇到过这个问题吗?提前致谢。 Live Link: JAVASCRIP
add/remove clone first row default not delete 添加/删除克隆第一行默认不删除&并获取正确的SrNo(例如:添加3行并在看到问题后删除SrNo.2)
我编码this ,但删除按钮不起作用。我在控制台中没有任何错误.. var counter = 0; var dataList = document.getElementById('materi
我有一个类似数组的对象: [1:数组[10]、2:数组[2]、3:数组[2]、4:数组[2]、5:数组[3]、6:数组[1]] 我正在尝试删除前两个元素,执行一些操作,然后将它们再次插入到同一位置。
使用的 Delphi 版本:2007 你好, 我有一个 Tecord 数组 TInfo = Record Name : String; Price : Integer; end; var Info
我使用了基本的 gridster 代码,然后我声明了通过按钮添加和删除小部件的函数它工作正常但是当我将调整大小功能添加到上面的代码中时,它都不起作用(我的意思是调整大小,添加和删除小部件) 我的js代
title 323 323 323 title 323 323 323 title 323 323 323 JS $(document).keydown(function(e){
我是一名优秀的程序员,十分优秀!