NoFieldsClass :: operator new (std :: size_t): позволяет ли стандарт возвращать один и тот же адрес при каждом вызове? - PullRequest
1 голос
/ 26 октября 2019

Как часть стратегии оптимизации, я хотел бы «притвориться», что я фактически выделяю объект в куче, тогда как на самом деле я просто использовал бы ранее существующий объект, не обращая внимания на остальную часть приложения, потому чтопроверка возвращаемого адреса не выполняется, и к полям из объектов никогда не будет обращаться. Кроме того, конструктор класса не имеет побочных эффектов.

Поэтому я хотел бы знать, демонстрирует ли следующая программа поведение, которое четко определено, зависит от реализации, не определено или недопустимо в целом, словомстандарт.

#include <memory>
#include <cassert>

class Base {
public:
    Base(){}
    virtual ~Base(){}
};

class Derived: public Base {
public:
    using Base::Base;

    static void *operator new(std::size_t s)  {
        static void *mem = ::operator new(s);

        return mem;
    }

    static void operator delete(void *mem) {
        /* no-op */
    }
};

int main() {
    using Ptr = std::unique_ptr<Base>;

    Ptr p1 { new Derived };
    Ptr p2 { new Derived };
    Ptr p3 { new Derived };
    Ptr p4 { new Derived };

    // assert just in this test, not in the real program
    assert(p1 == p2 && p2 == p3 && p3 == p4);

    return 0;
}

Чтение §6.7.2.9 текущего рабочего проекта C ++ ( N4835 ) кажется недопустимым:

Два объекта с перекрывающимися временами жизникоторые не являются битовыми полями, могут иметь один и тот же адрес, если одно вложено в другое, или если хотя бы один является подобъектом нулевого размера, и они имеют разные типы; в противном случае они имеют разные адреса и занимают непересекающиеся байты памяти ²⁹.

Однако примечание 29, на которое ссылается вышеприведенный абзац, гласит:

В соответствии с правилом «как если бы» реализации разрешено хранить два объекта с одинаковым машинным адресом или вообще не сохранять объект , если программа не может наблюдать разницу .

Как указывалось в начале, в моем случае программе было наплевать на адрес, по которому размещен этот объект, все, что требуется, - это то, что он может быть выделен с помощью operator new. и избавился от operator delete, так что, похоже, он соответствует требованиям, указанным в примечании 29. Это правильно?

1 Ответ

1 голос
/ 26 октября 2019

[basic.stc.dynamic.allocation] / 2 Функция выделения пытается выделить запрошенный объем памяти ... Если запрос выполнен успешно, возвращаемое значение должно быть незначение нулевого указателя (7.11) p0 отличается от любого ранее возвращенного значения p1, если только это значение p1 не было впоследствии передано operator delete.

Подчеркнутомой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...