what variable c++ initialization variable-assignment

what - variable size c++



Objetos que pueden inicializarse pero no asignarse (5)

Necesito crear una clase cuyos objetos se puedan inicializar pero no asignar.

Pensé que quizás podría hacer esto al no definir el operador de asignación, pero el compilador usa el constructor para realizar la tarea.

Necesito que sea de esta manera:

Object a=1; // OK a=1; // Error

¿Cómo puedo hacerlo?


Las funciones eliminadas están disponibles solo desde C ++ 11 en adelante, para compiladores más antiguos puede hacer que el operador de asignación sea private .

struct Object { Object(int) {} private: Object& operator=(int); };

El compilador lanzará un error para

Object a=1; //ok a=2; // error

Pero aún puedes hacer

Object a=1,b=2; b=a;

Debido a que el compilador no impide que el operador de asignación predeterminado sea generado. Por lo tanto, marcar la asignación predeterminada private resolverá este problema.

struct Object { Object(int) {} private: Object& operator=(Object&); };


¿Cómo puedo hacerlo?

Opción 1:

Haz que el constructor sea explicit

struct Object { explicit Object(int in) {} };

Opcion 2:

delete el operador de asignación.

struct Object { Object(int in) {} Object& operator=(int in) = delete; };

Puedes usar las dos opciones anteriores.

struct Object { explicit Object(int in) {} Object& operator=(int in) = delete; };

Opción 3:

Si no desea ninguna asignación después de la inicialización, puede delete el operador de asignación con Object como tipo de argumento.

struct Object { explicit Object(int in) {} Object& operator=(Object const& in) = delete; };

Eso evitará el uso de:

Object a(1); a = Object(2); // Error a = 2; // Error


Esperaba que esto fuera así al no definir el operador de asignación

Esto no funciona porque el operador de asignación de copia (que toma const Object& como parámetro) se genera implícitamente. Y cuando escriba a = 1 , se intentará invocar al operador de asignación de copias generado, y 1 podría convertirse implícitamente en Object mediante la conversión del constructor Object::Object(int) ; entonces a = 1; funciona bien.

Puede declarar el operador de asignación tomando int como eliminado (desde C ++ 11) explícitamente; que se seleccionará antes del operador de asignación de copias en la resolución de sobrecarga.

Si la función está sobrecargada, la resolución de sobrecarga se lleva a cabo primero, y el programa solo está mal formado si se seleccionó la función eliminada.

p.ej

struct Object { Object(int) {} Object& operator=(int) = delete; };

También hay algunas otras soluciones con efectos secundarios. Puede declarar Object::Object(int) como explicit para prohibir la conversión implícita de int a Object y luego hacer que a = 1 falle. Pero tenga en cuenta que esto hará que Object a = 1; también fallan porque la inicialización de copia no considera explicit constructor explicit . O puede marcar también el operador de asignación de copia eliminado, pero esto hará que la asignación entre Object también falle.


Hacer a const hará el truco

const Object a=1; // OK

Ahora no podrá asignar ningún valor a a como se declara como const . Tenga en cuenta que si declara a const , es necesario inicializar a en el momento de la declaración.

Una vez que haya declarado a const y también la haya inicializado, no podrá asignar ningún otro valor a a

a=1; //error


Puede eliminar el operador de asignación:

#include <iostream> using namespace std; struct Object { Object(int) {} Object& operator=(int) = delete; }; int main() { Object a=1; // OK a=1; // Error }

Solución alternativa

Puede usar la palabra clave explícita :

#include <iostream> using namespace std; struct Object { explicit Object(int) {} }; int main() { Object a(1); // OK - Uses explicit constructor a=1; // Error }

Actualizar

Según lo mencionado por user2079303 en los comentarios:

Vale la pena mencionar que la solución alternativa no evita la asignación regular de copiar / mover como a=Object(1)

Esto se puede evitar usando: Object& operator=(const Object&) = delete;