Порядок стека С++ утвержден?

Утверждается ли, что следующий код при каждой совместимой оптимизации компилятора возвращает значение 14? Это рекомендуется использовать? Является ли это более эффективным, чем введение двух указателей в общий массив? Есть ли у приведенной ниже техники стека конкретное имя? Какая лучшая практика дает точно такой же двоичный файл при компиляции с разумными или замечательными предположениями?

#include <iostream>

class A{
public:
    double x[10];
    double y[10];
};

int main(){
    A a;
    a.y[3] = 14;
    std::cout << a.x[13] << "\n";
}

Где я могу найти такие определения? (ссылки, ссылки). Я предполагаю, что есть трюк для эффективного чтения стандарта.

Замечание: сегодня я узнал, что GCC g++ 11.3.0 на Ubuntu 20.04 с оптимизацией -O3 -march=native -ffast-math на sandybridge не будет инициализировать статический int[10] нулями. Вот почему я педантичен. Кроме того, мой код, возможно, придется запускать на встроенных целях, где компиляторы могут быть сомнительными; но давайте держать это как отдельное рассмотрение.

fuse tee 29.03.2023 18:54

Нет такого требования. Если вы получаете результат, которого ожидаете, то только случайно.

Pete Becker 29.03.2023 18:57

Это неопределенное поведение для каждого совместимого компилятора. Кроме того, static int[10] не должен компилироваться с GCC g++ 11.3.0.

Eljay 29.03.2023 19:05

Один вопрос на вопрос, пожалуйста. Хотя в данном случае ответ один - не работает.

Slava 29.03.2023 19:16

Возможный дубликат stackoverflow.com/questions/1239938/…

Slava 29.03.2023 19:21

Помните, что C++ не обязательно должен использовать стек и, следовательно, не заботится о порядке стека.

user4581301 29.03.2023 19:23

@user4581301 user4581301 в данном случае я думаю, что это просто фигура речи, вопрос больше о макете объекта, чем о стеке как таковом.

Mark Ransom 29.03.2023 20:30

Язык C++ не гарантирует, что члены будут располагаться в памяти непрерывно. Компиляторам разрешено вставлять заполнение между элементами; но члены должны быть выложены в порядке объявления. Если вам нужны смежные значения, используйте массив.

Thomas Matthews 29.03.2023 20:35

@ThomasMatthews Я думаю, что проблема здесь глубже, чем заполнение и т. д. - компилятору разрешено полностью исключать незаконный код.

Slava 29.03.2023 21:23
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
9
79
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Некоторые люди уже указали в комментариях, что ваш код в настоящее время имеет неопределенное поведение.

Что касается упорядочения, вам гарантируется, что, как вы определили прямо сейчас, x и y находятся в порядке, то есть y будет иметь более высокий адрес памяти, чем x. Но между ними может быть отступ, чтобы было меньше перекрытий, чем вы ожидаете, или, возможно, вообще не было перекрытий. Кроме того, стандарт написан так, чтобы разрешать (но не требовать) проверку индексов массива на достоверность, поэтому даже если они находятся непосредственно рядом друг с другом, компилятору разрешено проверять это, поскольку вы определили x как 10 элементов. , любая попытка индексации за пределами элемента 10 th потерпит неудачу (например, вызовет аппаратное прерывание или сбой).

Это оставляет вопрос о том, как получить желаемый результат, но с определенным поведением. У вас есть несколько вариантов. Один из них заключается в выделении одного массива и добавлении псевдонима, который позволяет обрабатывать его половину, как если бы это был отдельный массив:

#include<iostream>

class A{
public:
    double x[20];
    double *y = &x[10];
};

int main(){
    A a;
    a.y[3] = 14;
    std::cout << a.x[13] << "\n";
}

Другое направление, в котором вы могли бы пойти, состояло бы в том, чтобы разделить два массива, но затем добавить небольшой прокси-сервер, чтобы разрешить адресацию в оба массива, как если бы они были одним:

#include<iostream>

class proxy {
    double *x_;
    size_t N;
    double *y_;
public:
    template <class T, std::size_t N>
    proxy(T (&x_)[N], T *y) : x_(x_), N(N), y_(y) {}

    double &operator[](std::size_t n) {
        if (n < N)
            return x_[n];
        else
            return y_[n-N];
    }
};

class A{
    double x_[10];
public:
    double y[10];
    proxy x{x_, y};
};

int main(){
    A a;
    a.y[3] = 14;
    std::cout << a.x[13] << "\n";
}

Если вам действительно не нужно использовать отдельные массивы для двух элементов, первый, вероятно, предпочтительнее — он явно проще и, вероятно, быстрее.

Рассматривать два массива как один опасно, потому что слишком заманчиво использовать их так, как если бы они были смежными, например, пытаясь записать их в двоичный файл.

Mark Ransom 29.03.2023 20:28

Это неопределенное поведение. Вы не можете гарантировать, что между массивами не будет заполнения.

Другие вопросы по теме