Pregunta

Tengo una pregunta acerca de algunas de cumplimiento C ++ estándar o la falta de ella.

En mi proyecto estoy usando alguna clase Guardia simple que utiliza el truco referencia constante. Estoy usando Visual Studio 2005 y hay dos configuraciones -. Uno para generación de versión normal y la segunda para las pruebas unitarias

En ambos casos hay una cierta colgante temporal en la referencia constante al final, pero lo que sucede en el ínterin es el problema. Para la configuración de liberación, los puntos de referencia const directamente a la temperatura creada en el regreso de la plantilla de función auxiliar que crea la instancia Guardia (sin constructor de copia se llama, ni siquiera una instancia para el caso).

Pero para conf prueba de unidad la temperatura plantilla de función se copia primero y luego su destructor se llama, haciendo lo que debe hacerse sólo después de la referencia constante se sale del ámbito.

He resuelto el problema mediante la desactivación de la guardia de copia original en la base de clase constructor (por lo que la acción de destructor no se desencadena para config para el que se llama al constructor de copia), pero lo que me molesta es la siguiente:

Es el comportamiento estándar compatible con la copia-temporal-? ¿La norma dice que la referencia const debe apuntar directamente a la temperatura, o se trata de un comportamiento definido por la implementación no se especifica en la norma?

He basado mi código más o menos sobre el artículo Guardia Alcance en gotw 88 El artículo de DDJ y Herb Sutter, pero ambos no parecen esas fuentes para tomar la llamada al destructor anterior de éstas.

Se observará Cualquier información de alguien con más conocimientos.

EDIT:

Bueno, el código es algo como esto:

class GuardBase
{
public:

  GuardBase() : m_enabled(true)
  {}

  //this is done because in normal build no copy constructor is called ( directly using the function temporary)
  //but for UT conf somehow the original temp is copied and destroyed
  GuardBase(const GuardBase& other)
  {
    other.disable();
  }

  void disable() const
  {
    m_enabled = false;
  }

protected:
  //member is mutable because we will access the object through the const reference
  mutable bool m_enabled;
};

template< typename Arg, typename ObjType, typename MemberMethod >
class Guard1Arg : public GuardBase 
{
public:
  Guard1Arg(ObjType& obj, MemberMethod remover,  Arg arg) : m_arg(arg), m_remover(remover), m_object(obj)
  {}

  ~Guard1Arg()
  {
    if ( m_enabled )
    {
      (m_object.*m_remover)(m_arg);
    }
  }

private:
  Arg m_arg;
  MemberMethod m_remover;
  ObjType& m_object;

  //this class should not be assigned
  Guard1Arg& operator=(const Guard1Arg& other);

};

//utility template function used to create Guards using member functions with 1 argument
template<typename MemberFunction, typename Obj, typename Arg>
Guard1Arg<Arg, Obj, MemberFunction> MakeGuard1Arg(Obj& obj, MemberFunction memberFunction, Arg& arg)
{
  return Guard1Arg<Arg, Obj, MemberFunction>(obj, memberFunction, arg);
}


#define GUARD_CREATE(arg, remover) const GuardBase& guard = MakeGuard1Arg(*this,  remover, arg);
#define GUARD_DISABLE guard.disable();
#define GUARD_FRIEND template< typename Arg, typename ObjType, typename MemberMethod > friend class Guard1Arg;
¿Fue útil?

Solución

Ambos comportamientos son normas que cumplen. Si usted tiene un código como este:

T foo()
{
  return T();
}

int main()
{
  const T& x = foo();
}

A continuación, conceptualmente, en foo, se crea un objeto temporal. Este temporal se copia en el retorno de valor de foo. En main, esta copia (que es también un objeto temporal) está obligado a x.
La copia que es el retorno del valor de foo pone su vida útil extendida, pero no el temporal que fue la fuente de la copia.

Sin embargo, el estándar C ++ permite explícitamente objetos temporales redundantes para ser elided. Así que en lugar de crear una copia temporal y que a lo largo en la ranura para valores de retorno, foo puede crear directamente el temporal en esa ranura.
Ambas opciones son posibles, y el compilador no tiene ni siquiera para documentar cuando utiliza la opción.

Las secciones pertinentes de la C ++ estándar son 6.6.3 ([stmt.return]) y 12.2 ([class.temporary]).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top