指针å¯äº’æ¢æ€§ä¸Žå…·æœ‰ç›¸åŒçš„地å€

时间:2017-12-21 11:35:15

标签: c++ arrays pointers language-lawyer c++17

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。

4 个答案:

答案 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)

仔细阅读标准的这一部分åŽï¼Œæˆ‘明白两个对象是指针å¯ç›¸äº’转æ¢çš„,顾åæ€ä¹‰ï¼Œå¦‚æžœ

  1. 它们通过它们的类定义“相互连接â€ï¼ˆè¯·æ³¨æ„,指针å¯ç›¸äº’转æ¢çš„概念是为类对象åŠå…¶ç¬¬ä¸€ä¸ªéžé™æ€æ•°æ®æˆå‘˜å®šä¹‰çš„)。

  2. 它们指å‘åŒä¸€ä¸ªåœ°å€ã€‚但是,由于它们的类型ä¸åŒï¼Œæˆ‘们需è¦ä½¿ç”¨ reinterpret_cast è¿ç®—符“转æ¢â€å®ƒä»¬çš„指针类型。

对于问题中æ到的数组对象,数组åŠå…¶ç¬¬ä¸€ä¸ªå…ƒç´ åœ¨ç±»å®šä¹‰æ–¹é¢æ²¡æœ‰äº’连,我们也ä¸éœ€è¦è½¬æ¢å®ƒä»¬çš„指针类型能够与它们一起工作。它们åªæ˜¯æŒ‡å‘åŒä¸€ä¸ªåœ°å€ã€‚