c++ - matrices - Cómo devolver una copia ''solo lectura'' de un vector
matrices en c++ (7)
¿Qué tal en lugar de devolver una referencia a su vector, devolver un nuevo tipo que envuelve el vector (contiene una referencia constante al vector) y expone solo la funcionalidad a la que desea permitir el acceso del llamante? Supongo que esto no es mucho ya que quiere evitar la mutabilidad del vector.
Tengo una clase que tiene un vector de atributo privado rectVec;
class A {
private:
vector<Rect> rectVec;
};
Mi pregunta es ¿cómo puedo devolver una copia de "solo lectura" de mi Vector? Estoy pensando en hacer esto:
class A {
public:
const vect<Rect>& getRectVec() { return rectVect; }
}
¿Es ese el camino correcto? Estoy pensando que esto puede protegerse contra la persona que llama modificar el vector (agregar / eliminar Rect en vector), ¿qué pasa con el Rect dentro del vector?
Básicamente, el uso de "const &" debería indicar a cualquier programador de C ++: se supone que no debes modificar esto. Si eres realmente paranoico, tendrás que clonar el vector.
En general esto es una mala práctica. Usted está exponiendo su implementación interna a sus llamadores. Es mejor que devuelva una instancia de clase contenedora (mencionada anteriormente) o que exponga las funciones que obtienen elementos o iteradores (tipográficos para que coincidan con su implementación)
Esa es la forma correcta, a menos que el usuario elimine la constancia utilizando const_cast
.
Esa es la forma correcta, aunque probablemente también querrá hacer que la función sea const
.
class A {
public:
const vect<Rect>& getRectVec() const { return rectVect; }
};
Esto hace que las personas puedan llamar a getRectVec
utilizando un objeto const A
Esa es la forma normal. const
significa "no puedes modificar esto". También se aplica a los elementos dentro del contenedor.
Una prueba simple:
#include <vector>
typedef std::vector<int> int_vec;
struct foo
{
const int_vec& get(void)
{
return v;
}
int_vec v;
};
int main(void)
{
foo f;
f.v.push_back(1);
f.v.push_back(2);
f.v.push_back(3);
f.get()[0] = 2; // nope
}
const_cast
podría usar const_cast
para eliminar la const
, pero luego terminaría con un comportamiento indefinido si modificara una variable a través de ella:
int_vec& v = const_cast<int_vec&>(f.get()); // this is okay
v[0] = 0; // but now we''ve entered undefined behavior
Sé que es una publicación bastante antigua, pero es uno de los mejores resultados de Google al buscar "c ++ read only vector". Es por eso que quiero publicar mi enfoque sin embargo.
Si desea que el contenedor en sí sea constante pero no sus elementos, puede utilizar un enfoque similar al siguiente:
template<class Container>
class Enumerable
{
public:
Enumerable(Container& container) : _container(container) {}
auto begin() const { return _container.begin(); }
auto end() const { return _container.end(); }
const Container& GetContainer() const { return _container; }
const Container* operator->() const { return &_container; }
private:
Container& _container;
};
Con eso, puede recorrer su contenedor y modificar sus elementos mientras se asegura que el contenedor se mantenga igual. Es posible que desee exponer una mayor funcionalidad del contenedor al especializar la clase para, por ejemplo, vectores al proporcionar un operador de indexación.
No estoy completamente seguro de si es un buen diseño para exponer un contenedor como ese, pero definitivamente es un patrón útil para algunos escenarios.