Pregunta ¿Por qué auto_ptr está en desuso?


he oído auto_ptr está en desuso en C ++ 11. ¿Cuál es la razón para esto?

También me gustaría saber la diferencia entre auto_ptr y shared_ptr.


74
2017-09-13 03:23


origen


Respuestas:


El reemplazo directo para auto_ptr (o lo más parecido a uno de todos modos) es unique_ptr. En lo que respecta al "problema", es bastante simple: auto_ptr transfiere la propiedad cuando está asignada. unique_ptr también transfiere la propiedad, pero gracias a la codificación de la semántica de movimientos y la magia de las referencias rvalue, puede hacerlo de forma mucho más natural. También "encaja" con el resto de la biblioteca estándar considerablemente mejor (aunque, para ser justos, parte de eso se debe a que el resto de la biblioteca cambia para adaptarse a la semántica de movimientos en lugar de requerir siempre la copia).

El cambio de nombre también es (IMO) bienvenido. auto_ptr realmente no dice mucho sobre lo que intenta automatizar, mientras que unique_ptr es una descripción bastante razonable (aunque concisa) de lo que se proporciona.


74
2017-09-13 03:45



Encontré excelentes las respuestas existentes, pero desde el PoV de los indicadores. IMO, una respuesta ideal debe tener la respuesta de perspectiva del usuario / programador.

Primero lo primero (como señaló Jerry Coffin en su respuesta)

  • auto_ptr podría ser reemplazado por shared_ptr o unique_ptr dependiendo de la situación

shared_ptr:  Si le preocupa la liberación de recursos / memoria Y si tiene más de una función que podría usar el objeto AT-DIFFERENT veces, vaya con shared_ptr.

En DIFERENTES veces, piense en una situación donde el objeto-ptr se almacena en una estructura de datos múltiple y luego se accede a él. Múltiples hilos, por supuesto, es otro ejemplo.

unique_ptr: Si todo lo que le preocupa es liberar memoria, y el acceso al objeto es SECUENCIAL, vaya a unique_ptr.

Por SECUENCIAL, quiero decir, en cualquier punto se accederá a un objeto desde un contexto. P.ej. un objeto que fue creado, y utilizado inmediatamente después de la creación por el creador. Después de la creación, el objeto se almacena en PRIMERO estructura de datos. Entonces, o bien el objeto se destruye después de la estructura de datos ONE o se mueve a SEGUNDO estructura de datos.

Desde esta línea, haré referencia a los _ptr compartidos / únicos como punteros inteligentes. (auto_ptr también es un puntero inteligente PERO debido a fallas en su diseño, por lo que están en desuso, y que creo que señalaré en las siguientes líneas, no deberían agruparse con puntero inteligente).

La razón más importante para determinar por qué auto_ptr quedó en desuso en favor de smart-pointer es    asignación semántica  Si no fuera por esa razón, habrían agregado todas las novedades de la semántica de movimientos al auto_ptr en lugar de desaprobarlo. Como la semántica de asignación era la característica más desagradable, querían que esa característica desapareciera, pero dado que hay un código escrito que usa esa semántica (que el comité de normas no puede cambiar), tuvieron que soltar auto_ptr, en lugar de modificándolo.

Desde el enlace: http://www.cplusplus.com/reference/memory/unique_ptr/operator=/

Tipo de asignaciones admitidas por unqiue_ptr 

  • mover asignación (1)
  • Asignar puntero nulo (2)
  • asignación de tipografía (3)
  • copia de asignación (¡eliminado!) (4)

De : http://www.cplusplus.com/reference/memory/auto_ptr/operator=/

Tipo de asignaciones admitidas por auto_ptr 

  • copia de asignación (4) culpable

Ahora, llegando a la razón por la cual la asignación de copia en sí misma era tan desagradable, tengo esta teoría:

  1. No todos los programadores leen libros o estándares
  2. auto_ptr a la vista, le promete la propiedad del objeto
  3. la cláusula little- * (juego de palabras) de auto_ptr, que no es leída por todos los programadores, permite la asignación de un auto_ptr a otro y transfiere la propiedad.
  4. La investigación ha demostrado que este comportamiento está destinado al 3.1415926535% del uso total y no intencional en otros casos.

El comportamiento no deseado es realmente desagradable y, por lo tanto, el desagrado por el auto_ptr.

(Para el 3.1415926536% de los programadores que intencionalmente quieren transferir la propiedad C ++ 11 les dio std :: move (), lo que hizo que su intención fuera clara para todos los internos que iban a leer y mantener el código).


29
2018-02-24 06:12



shared_ptr puede ser almacenado dentro de contenedores. auto_ptr hipocresía.

Por cierto unique_ptr es realmente el directo auto_ptr reemplazo, combina las mejores características de ambos std::auto_ptr y boost::scoped_ptr.


20
2017-09-13 03:27



Otra explicación para explicar la diferencia ...

Funcionalmente, C ++ 11 std::unique_ptr es el "fijo" std::auto_ptr: ambos son adecuados cuando, en cualquier punto durante la ejecución, debe haber un único propietario de puntero inteligente para un objeto apuntado.

La diferencia crucial es en la construcción de copias o la asignación desde otro puntero inteligente que no expira, que se muestra en el => líneas a continuación:

   std::auto_ptr<T> ap(...);
   std::auto_ptr<T> ap2(get_ap_to_T());   // take expiring ownership
=> std::auto_ptr<T> ap3(ap);  // take un-expiring ownership ala ap3(ap.release());
   ap->xyz;  // oops... can still try to use ap, expecting it to be non-NULL

   std::unique_ptr<T> up(...);
   std::unique_ptr<T> up2(get_up_to_T());   // take expiring ownership
=> std::unique_ptr<T> up3(up);  // COMPILE ERROR: can't take un-expiring ownership
=> std::unique_ptr<T> up4(std::move(up));  // EXPLICIT code allowed
=> std::unique_ptr<T> up4(up.release());   // EXPLICIT code allowed

Encima, ap3 silenciosamente "roba" la propiedad de *ap, dejando ap establecer a nullptr, y el problema es que puede suceder muy fácilmente, sin que el programador haya pensado en su seguridad.

Por ejemplo, si class/struct tiene un std::auto_ptr miembro, luego hacer una copia de una instancia release el puntero de la instancia que se está copiando: eso es una semántica extraña y peligrosamente confusa ya que generalmente copiar algo no lo modifica. Es fácil para el autor de la clase / estructura pasar por alto el lanzamiento del puntero al razonar sobre invariantes y el estado, y consecuentemente intentar accidentalmente desreferenciar el puntero inteligente mientras está nulo, o simplemente no tener el acceso / propiedad esperado de los datos apuntados.


6
2018-02-12 04:21



auto_ptr no se puede usar en contenedores STL porque tiene un constructor de copia que no cumple con los requisitos del contenedor CopyConstructible. unique_ptr no implementa un constructor de copia, por lo que los contenedores utilizan métodos alternativos. unique_ptr se puede usar en contenedores y es más rápido para algoritmos std que shared_ptr.

#include <iostream>
#include <type_traits>
#include <vector>
#include <memory>

using namespace std;

int main() {
  cout << boolalpha;
  cout << "is_copy_constructible:" << endl;
  cout << "auto_ptr: " << is_copy_constructible< auto_ptr<int> >::value << endl;
  cout << "unique_ptr: " << is_copy_constructible< unique_ptr<int> >::value << endl;
  cout << "shared_ptr: " << is_copy_constructible< shared_ptr<int> >::value << endl;

  vector<int> i_v;
  i_v.push_back(1);
  cout << "i_v=" << i_v[0] << endl;
  vector<int> i_v2=i_v;
  cout << "i_v2=" << i_v2[0] << endl;

  vector< unique_ptr<int> > u_v;
  u_v.push_back(unique_ptr<int>(new int(2)));
  cout << "u_v=" << *u_v[0] << endl;
  //vector< unique_ptr<int> > u_v2=u_v;  //will not compile, need is_copy_constructible == true
  vector< unique_ptr<int> > u_v2 =std::move(u_v);  // but can be moved
  cout << "u_v2=" << *u_v2[0] << " length u_v: " <<u_v.size() << endl;

  vector< shared_ptr<int> > s_v;
  shared_ptr<int> s(new int(3));
  s_v.push_back(s);
  cout << "s_v=" << *s_v[0] << endl;
  vector< shared_ptr<int> > s_v2=s_v;
  cout << "s_v2=" << *s_v2[0] << endl;

  vector< auto_ptr<int> > a_v;  //USAGE ERROR

  return 0;
}

>cxx test1.cpp -o test1
test1.cpp: In function âint main()â:
test1.cpp:33:11: warning: âauto_ptrâ is deprecated (declared at /apps/hermes/sw/gcc/gcc-4.8.5/include/c++/4.8.5/backward/auto_ptr.h:87) [-Wdeprecated-declarations]
   vector< auto_ptr<int> > a_v;  //USAGE ERROR
           ^
>./test1
is_copy_constructible:
auto_ptr: false
unique_ptr: false
shared_ptr: true
i_v=1
i_v2=1
u_v=2
s_v=3
s_v2=3

2
2017-07-11 19:02