Como programador novato en C++ hay algunas construcciones que aún me parecen muy poco claras, una de ellas es const
. Puedes usarlo en muchos lugares y con tantos efectos diferentes que es casi imposible que un principiante salga con vida. ¿Algún gurú de C++ explicará una vez para siempre los diversos usos y si y por qué no usarlos?¿Cuántos y cuales son los usos de "const" en C++?
Respuesta
Tratando de recoger algunos usos:
unión temporal alguna para hacer referencia a const, para alargar su vida útil. La referencia puede ser una base - y el destructor de la misma no tenga que ser virtuales - el destructor derecha todavía se llama:
ScopeGuard const& guard = MakeGuard(&cleanUpFunction);
Explicación, utilizando el código:
struct ScopeGuard {
~ScopeGuard() { } // not virtual
};
template<typename T> struct Derived : ScopeGuard {
T t;
Derived(T t):t(t) { }
~Derived() {
t(); // call function
}
};
template<typename T> Derived<T> MakeGuard(T t) { return Derived<T>(t); }
Este truco se utiliza en la clase de utilidad ScopeGuard de Alexandrescu. Una vez que el temporal se sale del alcance, el destructor de Derived se llama correctamente. El código anterior omite algunos pequeños detalles, pero ese es el gran problema.
Uso const para decirle a otros métodos no cambiará el estado lógico de este objeto.
struct SmartPtr {
int getCopies() const { return mCopiesMade; }
};
Uso const para las clases de copia en escritura, para hacer que el compilador de ayuda a decidir cuándo y cuándo no es necesario copiar.
struct MyString {
char * getData() { /* copy: caller might write */ return mData; }
char const* getData() const { return mData; }
};
Explicación: Es posible que desee compartir datos cuando se copia algo, siempre y cuando los datos del origen y el objeto copie'd siguen siendo los mismos. Una vez que uno de los objetos cambia los datos, usted necesita ahora dos versiones: una para el original y otra para la copia. Es decir, copia en un escribe para cualquier objeto, de modo que ahora ambos tengan su propia versión.
El uso de código:
int main() {
string const a = "1234";
string const b = a;
// outputs the same address for COW strings
cout << (void*)&a[0] << ", " << (void*)&b[0];
}
Las impresiones de los anteriores fragmentos de la misma dirección en mi GCC, porque la biblioteca se utiliza C++ implementa una copia en escritura std::string
. Ambas cadenas, aunque son objetos distintos, comparten la misma memoria para sus datos de cadena. Hacer b
no const preferirá la versión no const de operator[]
y GCC creará una copia del buffer de memoria de respaldo, porque podríamos cambiarlo y no debe afectar los datos de a
!
int main() {
string const a = "1234";
string b = a;
// outputs different addresses!
cout << (void*)&a[0] << ", " << (void*)&b[0];
}
Para el constructor de copia para hacer copias de objetos const y temporales:
struct MyClass {
MyClass(MyClass const& that) { /* make copy of that */ }
};
Para hacer constantes que trivialmente no puede cambiar
double const PI = 3.1415;
Para pasar objetos arbitrarios por referencia en lugar de por valor - para prevenir posiblemente caro o imposible por valor de pasar
void PrintIt(Object const& obj) {
// ...
}
¿Puede explicar el primer y el tercer uso en sus ejemplos? – tunnuz
"Para garantizar al destinatario que el parámetro no puede ser NULO" No veo cómo const tiene algo que ver con ese ejemplo. –
¡Uy, así que no! de alguna manera comencé a escribir sobre referencias. muchas gracias por gemir :) por supuesto eliminaré eso ahora :) –
En realidad, hay 2 principales usos de const en C++.
Const valora
Si un valor es en forma de una variable, miembro, o parámetro que no (o no debe) ser alterado durante su vida útil debe marcarlo const. Esto ayuda a prevenir mutaciones en el objeto. Por ejemplo, en la siguiente función no necesito cambiar la instancia de Estudiante pasada, así que lo marqué const.
void PrintStudent(const Student& student) {
cout << student.GetName();
}
En cuanto a por qué harías esto. Es mucho más fácil razonar acerca de un algoritmo si sabes que los datos subyacentes no pueden cambiar. "const" ayuda, pero no garantiza que esto se logre.
Obviamente, los datos de impresión a cout no exige mucho pensamiento :)
Marcado miembro de un método como const
En el ejemplo anterior he marcado estudiante como const. Pero, ¿cómo sabía C++ que llamar al método GetName() en el alumno no mutaría el objeto? La respuesta es que el método fue marcado como const.
class Student {
public:
string GetName() const { ... }
};
Marcado de un método "const" hace 2 cosas. En primer lugar, le dice a C++ que este método no mutará mi objeto. Lo segundo es que todas las variables miembro se tratarán ahora como si estuvieran marcadas como const. Esto ayuda pero no evita que modifiques la instancia de tu clase.
Este es un ejemplo extremadamente simple pero espero que ayude a responder sus preguntas.
Tenga cuidado para entender la diferencia entre estos 4 declaraciones:
Las siguientes declaraciones son idénticos 2 semánticamente. Puede cambiar donde punto ccp1 y ccp2, pero no puede cambiar lo que están apuntando.
const char* ccp1;
char const* ccp2;
A continuación, el puntero es constante, así sea significativa debe ser inicializado para apuntar a algo.No puede hacer que apunte a otra cosa, sin embargo, lo que apunta a puede cambiar.
char* const cpc = &something_possibly_not_const;
Por último, combinamos los dos - así que lo que se apunta a no puede ser modificado, y el puntero no podemos señalar a cualquier otro lugar.
regla espiralconst char* const ccpc = &const_obj;
El agujas del reloj puede ayudar a desenredar una declaración http://c-faq.com/decl/spiral.anderson.html
De una manera indirecta, sí lo hace! La regla espiral en el sentido de las agujas del reloj lo describe mejor: comience por el nombre (kpPointer) y dibuje una espiral en el sentido de las agujas del reloj que salga por el token, y diga cada token. Obviamente, no hay nada a la derecha de kpPointer, pero aún funciona. –
Como una pequeña nota, mientras leía here, es útil notar que
const
se aplica a lo que está en su inmediata left (excepto si no hay nada allí en cuyo caso se aplica a lo que sea que sea su inmediato a la derecha).
- 1. ¿Cuáles son algunos usos prácticos para las variables const const en C?
- 2. IComparable algunos de los cuales son nulos
- 3. ¿Cómo funciona jemalloc? ¿Cuales son los beneficios?
- 4. ¿Cuáles son los usos de funciones virtuales puras en C++?
- 5. ¿Cuáles son todos los usos de '@' en C#?
- 6. ¿Cuáles son los usos de la construcción C++ "placement new"?
- 7. ¿Cuáles son los usos de svn copy?
- 8. ¿Cuáles son los usos comunes de UDP?
- 9. ¿Cuáles son los usos de Cross Join?
- 10. ¿Cuáles son los usos de buffer circular?
- 11. ¿Cuáles son los diferentes usos de los [corchetes] en Ruby?
- 12. C# Atributos y sus usos
- 13. ¿Cuáles son los usos inusuales y creativos del lienzo html5
- 14. ¿Cuántos EJB son demasiados?
- 15. ¿Cuáles son los usos de los tipos polimórficos?
- 16. ¿Cuáles son los buenos usos de los módulos empaquetados OCaml?
- 17. ¿Cuáles son los usos de las subrutinas lvalue en Perl?
- 18. ¿Cuáles son los usos del predicado de falla en Prolog?
- 19. ¿Cuáles son los usos prácticos del módulo (%) en la programación?
- 20. const y no const methods in C++?
- 21. ¿Cuáles son algunos usos de los cierres para OOP?
- 22. ¿Cuáles son algunos usos de los parámetros de plantilla de plantilla en C++?
- 23. ¿Cuáles son algunos usos de los metadatos de Clojure?
- 24. ¿Cuáles son los usos prácticos de Factory Method Pattern?
- 25. Iron Python: cuáles son los buenos usos de Iron Python
- 26. ¿Cuáles son algunos de los usos inteligentes de LINQ?
- 27. ¿Cuáles son los mejores usos de las tiendas de documentos?
- 28. ¿Cuáles son los usos comunes de las variables de condición en C++?
- 29. ¿Cuáles son los usos prácticos de un constructor protegido?
- 30. ¿Cuáles son los usos del código de auto modificación?
buscando exactamente esa pregunta: D – alamin