working draft of the standard N4659说:
 Â[basic.compound]
  如果两个对象是指针å¯äº’æ¢çš„,那么它们具有相åŒçš„地å€
然åŽæ³¨æ„到
 Â数组对象åŠå…¶ç¬¬ä¸€ä¸ªå…ƒç´ ä¸æ˜¯æŒ‡é’ˆå¯äº’æ¢çš„,å³ä½¿å®ƒä»¬å…·æœ‰ç›¸åŒçš„地å€
使数组对象åŠå…¶ç¬¬ä¸€ä¸ªå…ƒç´ éžæŒ‡é’ˆå¯äº’æ¢çš„基本原ç†æ˜¯ä»€ä¹ˆï¼Ÿæ›´ä¸€èˆ¬åœ°è¯´ï¼ŒåŒºåˆ†æŒ‡é’ˆ - å¯äº’æ¢æ€§æ¦‚念与具有相åŒåœ°å€çš„概念的ç†ç”±æ˜¯ä»€ä¹ˆï¼Ÿåœ¨é‚£é‡ŒæŸå¤„ä¸å˜åœ¨çŸ›ç›¾å—?
看æ¥è¿™ä¸ªé™ˆè¿°åºåˆ—
p1 == p2
我们有i1
,但i2
已明确定义,使用try {
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress(
"sender@gmail.com"));
message.setRecipients(Message.RecipientType.TO,
InternetAddress.parse("reciever@gmail.com"));
message.setSubject("subject");
Multipart multipart = new MimeMultipart();
URL url = new URL(url);
InputStream is = url.openStream();
MimeBodyPart bodyPart = new MimeBodyPart(is);
multipart.addBodyPart(bodyPart);
message.setContent(multipart);
message.addHeader("Content-Type", mimeType);
Transport.send(message);
logger.info("SENT to" + message.getRecipients(RecipientType.TO));
} catch (MessagingException e) {
//some implementation
}
会产生UB。
ç”案 0 :(得分:18)
显然å˜åœ¨åŸºäºŽæ¤ä¼˜åŒ–的实现。考虑:
struct A {
double x[4];
int n;
};
void g(double* p);
int f() {
A a { {}, 42 };
g(&a.x[1]);
return a.n; // optimized to return 42;
// valid only if you can't validly obtain &a.n from &a.x[1]
}
鉴于p = &a.x[1];
,g
å¯èƒ½ä¼šå°è¯•a.n
获å–对reinterpret_cast<A*>(reinterpret_cast<double(*)[4]>(p - 1))->n
的访问æƒé™ã€‚如果内部强制转æ¢æˆåŠŸåœ°äº§ç”Ÿäº†æŒ‡å‘a.x
的指针,则外部强制转æ¢å°†äº§ç”ŸæŒ‡å‘a
的指针,从而使类æˆå‘˜è®¿é—®å®šä¹‰çš„行为,从而ç¦æ¢ä¼˜åŒ–。
ç”案 1 :(得分:3)
 Â更一般地说,将指针 - å¯äº’æ¢æ€§çš„概念与具有相åŒåœ°å€çš„概念区分开æ¥çš„ç†ç”±æ˜¯ä»€ä¹ˆï¼Ÿ
如果ä¸æ˜¯ä¸å¯èƒ½å›žç”ä¸ºä»€ä¹ˆæ ‡å‡†åšå‡ºæŸäº›å†³å®šå¾ˆéš¾ï¼Œä½†è¿™æ˜¯æˆ‘的看法。
逻辑上,指针指å‘对象,而ä¸æ˜¯åœ°å€ã€‚地å€æ˜¯æŒ‡é’ˆçš„值表示。é‡ç”¨åŒ…å«const
æˆå‘˜
struct S {
const int i;
};
S s = {42};
auto ps = &s;
new (ps) S{420};
foo(ps->i); // UB, requires std::launder
å¯ä»¥ä½¿ç”¨å…·æœ‰ç›¸åŒå€¼è¡¨ç¤ºçš„指针,就好åƒå®ƒæ˜¯ç›¸åŒçš„æŒ‡é’ˆä¸€æ ·ï¼Œåº”è¯¥è¢«è®¤ä¸ºæ˜¯ç‰¹æ®Šæƒ…å†µè€Œä¸æ˜¯ç›¸åçš„æ–¹å¼ã€‚
å®žé™…ä¸Šï¼Œè¯¥æ ‡å‡†è¯•å›¾å°½å¯èƒ½å°‘地é™åˆ¶å®žçŽ°ã€‚ 指针å¯äº’æ¢æ€§æ˜¯æŒ‡é’ˆå¯èƒ½æ˜¯reinterpret_cast
并产生æ£ç¡®ç»“果的æ¡ä»¶ã€‚看到reinterpret_cast
如何被编译æˆä»€ä¹ˆéƒ½æ²¡æœ‰ï¼Œå®ƒä¹Ÿæ„味ç€æŒ‡é’ˆå…±äº«ç›¸åŒçš„å€¼è¡¨ç¤ºã€‚ç”±äºŽè¿™å¯¹å®žæ–½æ–½åŠ äº†æ›´å¤šé™åˆ¶ï¼Œå› æ¤åœ¨æ²¡æœ‰ä»¤äººä¿¡æœçš„ç†ç”±çš„情况下ä¸ä¼šç»™å‡ºæ¡ä»¶ã€‚
ç”案 2 :(得分:2)
å› ä¸ºå§”å‘˜ä¼šå¸Œæœ›æ˜Žç¡®è¡¨ç¤ºæ•°ç»„æ˜¯ä½Žçº§æ¦‚å¿µè€Œä¸æ˜¯ç¬¬ä¸€ç±»å¯¹è±¡ï¼šä¾‹å¦‚,您ä¸èƒ½è¿”回数组也ä¸èƒ½åˆ†é…它。指针å¯äº’æ¢æ€§æ˜¯æŒ‡ç›¸åŒçº§çš„å¯¹è±¡ä¹‹é—´çš„æ¦‚å¿µï¼šä»…æ ‡å‡†å¸ƒå±€ç±»æˆ–è”åˆã€‚
这个概念在整个è‰æ¡ˆä¸å¾ˆå°‘使用:在[expr.static.cast]ä¸å®ƒä½œä¸ºç‰¹ä¾‹å‡ºçŽ°ï¼Œåœ¨[class.mem]ä¸ï¼Œæ³¨é‡Šè¡¨ç¤ºå¯¹äºŽæ ‡å‡†å¸ƒå±€ç±»ï¼ŒæŒ‡é’ˆæ˜¯ä¸€ä¸ªå¯¹è±¡åŠå…¶ç¬¬ä¸€ä¸ªå对象是å¯äº’æ¢çš„,在[class.union]ä¸ï¼ŒæŒ‡å‘union的指针åŠå…¶éžé™æ€æ•°æ®æˆå‘˜ä¹Ÿåœ¨[ptr.launder]ä¸å£°æ˜Žä¸ºå¯äº’æ¢çš„。
最åŽä¸€æ¬¡å‡ºçŽ°ä¸¤ä¸ªç”¨ä¾‹ï¼šæŒ‡é’ˆæ˜¯å¯äº’æ¢çš„ï¼Œæˆ–è€…ä¸€ä¸ªå…ƒç´ æ˜¯ä¸€ä¸ªæ•°ç»„ã€‚è¿™åœ¨ä¸€ä¸ªæ³¨é‡Šä¸è¯´æ˜Žï¼Œè€Œä¸æ˜¯åœ¨[basic.compound]ä¸çš„注释ä¸ï¼Œå› æ¤å®ƒæ›´æ¸…楚地表明指针 - 互æ¢æ€§è‡ªæ„¿ä¸æ¶‰åŠæ•°ç»„。
ç”案 3 :(得分:1)
ä»”ç»†é˜…è¯»æ ‡å‡†çš„è¿™ä¸€éƒ¨åˆ†åŽï¼Œæˆ‘明白两个对象是指针å¯ç›¸äº’转æ¢çš„,顾åæ€ä¹‰ï¼Œå¦‚æžœ
它们通过它们的类定义“相互连接â€ï¼ˆè¯·æ³¨æ„,指针å¯ç›¸äº’转æ¢çš„概念是为类对象åŠå…¶ç¬¬ä¸€ä¸ªéžé™æ€æ•°æ®æˆå‘˜å®šä¹‰çš„)。
它们指å‘åŒä¸€ä¸ªåœ°å€ã€‚但是,由于它们的类型ä¸åŒï¼Œæˆ‘们需è¦ä½¿ç”¨ reinterpret_cast
è¿ç®—符“转æ¢â€å®ƒä»¬çš„指针类型。
对于问题ä¸æ到的数组对象,数组åŠå…¶ç¬¬ä¸€ä¸ªå…ƒç´ 在类定义方é¢æ²¡æœ‰äº’连,我们也ä¸éœ€è¦è½¬æ¢å®ƒä»¬çš„指针类型能够与它们一起工作。它们åªæ˜¯æŒ‡å‘åŒä¸€ä¸ªåœ°å€ã€‚