Valor de retorno de la colocación nuevo


Considere el siguiente código C++14:

#include <cassert>
#include <new>
#include <type_traits>

struct NonStandardLayout
{
    // ...
};

int main()
{
    using T = NonStandardLayout;

    std::aligned_storage_t< sizeof(T), alignof(T) > storage;
    T *const valid_ptr = new(static_cast<void *>(&storage)) T;

    T *const maybe_ptr = reinterpret_cast<T *>(&storage);
    assert(maybe_ptr == valid_ptr); // ???

    valid_ptr->T::~T();
    return 0;
}

¿Está garantizado por el estándar que la afirmación en el ejemplo nunca fallará, para cualquier tipo T?

Discusión

Buscando en el último estándar ( http://eel.is/c++draft / ), no puedo ver ninguna referencia a este escenario en particular, pero he encontrado los siguientes párrafos que posiblemente apuntan a la respuesta "sí".

¿Es correcto de mi parte pensar que [expr.new/15] y [nuevo.eliminar.colocación/2] junto establece que el valor de valid_ptr será igual a la dirección de storage, siempre?

Si es así, es cierto que el reinterpret_cast producirá un puntero a un objeto construido? Porque, [expr.reinterpretar.reparto / 7], [expr.estática.reparto / 13] y [básica.compuesto/4] juntos parecen indicar que debería ser el caso.

De mis observaciones, las implementaciones de bibliotecas del asignador predeterminado parecen ser similares a esto y sin preocupaciones! Es realmente seguro lanzar así?

Cómo ¿podemos estar seguros de que los dos indicadores serán los mismos, o podemos?

Author: Jean-François Fabre, 2016-11-30

2 answers

Me sorprende que nadie haya mencionado este contraejemplo barato todavía:

struct foo {
  static foo f;
  // might seem dubious but doesn't violate anything
  void* operator new(size_t, void* p) {return &f;}
};

Demo en Coliru .

Sin embargo, a menos que se llame a una versión de colocación específica de clase, su aserción debería mantenerse. Ambas expresiones tienen que representar la misma dirección como se explica en la otra respuesta (el punto principal es que el estándar non-allocating operator new simplemente devuelve el argumento puntero y la nueva expresión no hace nada sofisticado), y ninguno de estos es un puntero pasado el final de algún objeto así, por [expr.eq] / 2, comparan igual.

 5
Author: Columbo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-28 11:00:31

18.6.1.3 Formularios de colocación [nuevo.eliminar.colocación]

Void* operator new (std:: size_t size, void * ptr) noexcept;

Devuelve: ptr.

Se especifica inequívocamente que el operador placement new devuelve cualquier puntero que se le pase. "Devuelve: ptr". No puedo ser más claro que eso.

Eso, más o menos, sella el trato para mí en cuanto a" el valor devuelto de la colocación nueva " va: la colocación new no hace nada al puntero que coloca, y siempre devuelve el mismo puntero.

Todo lo demás en su pregunta se relaciona con cualquier otro cambio que pueda ocurrir como resultado de los otros casts; pero está preguntando específicamente sobre el valor devuelto de la colocación new, así que entiendo que está aceptando que todas las demás conversiones son solo conversiones de tipo, y no tienen ningún efecto sobre el puntero real, y solo estaba preguntando sobre la colocación nueva but pero también sería posible pasar por los otros casts, y hacer una determinación.

 0
Author: Sam Varshavchik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-30 20:47:01