Порядок виконання оператора new та аргумент конструктора


9

Чи вказує специфікація C ++ порядок operator newі конструктор Aв new C(A()).
G ++ нехай порядок буде A()-> new-> C(), але clang ++ нехай буде new-> A()-> C().
Чи різниця викликана невказаною поведінкою?

г ++: 7.4.0 кланг ++: 10.0.0

#include <iostream>
#include <cstdlib>

struct A {
    A() {
        std::cout << "call A()\n";
    }
};

struct C {
    C(A) {
        std::cout << "call S()\n";
    }

    void *operator new(size_t s) {
        std::cout << "call new()\n";
        return malloc(s);
    }
};

int main() {
    void *p = new C(A());
}

3
Ви будуєте як C ++ 17, C ++ 14 чи попередній?
StoryTeller - Невідповідна Моніка

4
Дві примітки: Ви позначили це тегом "C", що чітко показує, що ви не прочитали опис цього тегу. Не варто. Тепер ви запитуєте про "невизначену поведінку" (UB). Це термін, який використовується стандартом C ++ для позначення речей, де все може статися і чого слід уникати. Існує також "невизначена поведінка", яка, ймовірно, ближче до того, що ви хочете, оскільки код технічно непоганий і не викликає UB.
Ульріх Екхардт

1
@Ulrich Eckhardt Дякую за пропозицію. Я змішав два.
eddie kuo

Відповіді:


11

Кланг правильний. Оскільки на C ++ 17 порядок виконання гарантується. [expr.new] / 19

Викликання функції розподілу секвенується перед оцінками виразів у новому ініціалізаторі .

operator new(функцію розподілу) слід спочатку викликати, а потім оцінку вираження в новому ініціалізаторі (тобто A()).

Перед C ++ 17 замовлення не гарантується. [expr.new] / 18 (C ++ 14)

Викликання функції розподілу невизначено секвенується щодо оцінок виразів у новому ініціалізаторі .


Здається, що gcc не відповідає C ++ 17 (і пізніших версіях); компіляція з gcc10 в режимі C ++ 2a дає такий же результат.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.