2009-12-21 8 views
14

Tengo una serie de clases que me gustaría explícitamente no permitir la asignación de montón. Se me ocurrió este fin de semana que podría declarar operador nuevo privado (y no implementado) ... Efectivamente, esto da como resultado errores de compilación cuando intentas volver a la clase ... Mi pregunta es: ¿hay más en esto? ¿Me estoy perdiendo algo o es esta una buena manera de hacer lo que quiero?Rechazar explícitamente la asignación de montón en C++

#include <stdio.h> 

class NotOnTheHeap 
{ 
public: 
    NotOnTheHeap() : foo(0) 
    { 
    } 

private: 
    void *operator new(size_t); 
    void operator delete(void*); 
    void *operator new[](size_t); 
    void operator delete[](void*); 

    int foo; 
}; 

class Heapable 
{ 
private: 
    NotOnTheHeap noth; 
}; 

int main(int argc, char* argv[]) 
{ 
    NotOnTheHeap noth; 

    Heapable* heapable = new Heapable; 

    return 0; 
} 
+2

¿Por qué quiere restringir estas clases? – GManNickG

+3

@GManNickG Es posible que desee restringirlo por razones de rendimiento y arquitectura. Por qué se puede instruir a los programadores para que no lo hagan, es bueno tener las cosas en su lugar que * ayuden * a lograr esto. Por lo tanto, se detectan infracciones accidentales o no intencionadas de la regla. Probablemente sea más simple si su propia clase pudiera hacer cumplir esto en vez de intentar escribir una regla de análisis estático para hacerlo. – iheanyi

Respuesta

11

Depende de lo que quiere decir con "explícitamente no permitir la asignación de montón".

Si lo que desea es evitar la asignación directa en el montón, es decir .:

NotOnTheHeap *n = new NotOnTheHeap(); 

es lo suficientemente bueno. Pero no impedirá que su objeto exista en el montón en general.

Por ejemplo, no impedirá que las personas usen std::vector <NotOnTheHeap>, que asignará objetos de su clase en el montón.

Tampoco impedirá que las personas usen un NotOnTheHeap como variable miembro en otra clase, que se asigna en el montón.

+2

Especificando explícitamente la función de asignación, ':: new A', también funciona. –

+1

Sí, me di cuenta de esto ... Es por eso que tenía "Heapable" en el ejemplo ... Para mostrar que todavía podría existir en el montón indirectamente ... – dicroce

0

¿No puedes simplemente hacer la implementación del operador new a assert (0)?

+22

Creo que un error de tiempo de compilación es mejor que permitir que el código compile realmente y luego muera en tiempo de ejecución. –

+2

Los errores de compilación son mejores que los afirmados. – dicroce

+1

Para ser un poco más preciso, este es un error de tiempo de enlace (que aún es preferible a un error de tiempo de ejecución). –

1

Eso logrará principalmente lo que está intentando.

Lo que su solución no cubre es in situ nuevo, que puede o no estar en el montón.

+1

¿Se puede extender para cubrir la colocación nueva? – dicroce

+2

No, la colocación nueva no es reemplazable. Simplemente devuelve la dirección que se le dio. – GManNickG

+0

El código tal como está en la pregunta ya cubre la colocación nueva: 'new (some_void_ptr) A' fallará.No cubre ':: new (some_void_ptr) A' porque cuando la función de asignación se especifica explícitamente, las sobrecargas de clase no se consideran (se aplica a todos los formularios de ubicación, así como a la no colocación, por ejemplo' :: new A') . No estoy seguro de por qué GMan menciona esto, porque puedes declarar 'A :: operador nuevo (tamaño_t, vacío *)', etc., solo puedes reemplazar ':: operador nuevo (tamaño_t, vacío *)', pero el código nunca reemplaza el '' operador new (size_t) 'global tampoco. –

1

Puede deshabilitar la copia o incluso la construcción predeterminada, y operator = etc para un escenario más estricto (algunos casos de valores de incrustación o uso de contenedores).

Sin embargo, eso lo eliminará de algunas construcciones útiles y lo forzará a introducir su propia semántica (algo más visible en VM implica, falta/inducción de operador similar y mecanismos ambiguos de equivalencia/igualdad). Es probable que también vea algunas advertencias del compilador, no llegará hasta el final, pero si sirve de consuelo, puede tener uno o dos usos.

-2

Ponte en contacto con el efectivo C++ de Scott Meyers y el C++ más efectivo: cubre este tipo de cosas. Cada programador de C++ debe poseer & leer estos libros.

+0

Buen libro, pero -1 por no responder en realidad la pregunta. – ipapadop

Cuestiones relacionadas