Domanda

Ho una domanda su alcuni conformità C ++ standard o la mancanza di esso.

Nel mio progetto che sto utilizzando qualche semplice classe Guardia che usa il trucco di riferimento const. Sto usando Visual Studio 2005 e ci sono due configurazioni -. Uno per la normale build di rilascio e la seconda per i test unitari

In entrambi i casi v'è una certa appeso temporanea sul riferimento const alla fine, ma ciò che accade nel frattempo è il problema. Per la configurazione di rilascio, i punti di riferimento const direttamente alla temperatura creato nel ritorno del modello di funzione di supporto che crea l'istanza Guardia (nessun costruttore di copia è chiamato, nemmeno un'istanza per questo).

Ma per test di unità conf la temperatura modello di funzione viene prima copiato e quindi il suo distruttore viene chiamato, facendo quello che dovrebbe essere fatto solo dopo che il riferimento const va fuori del campo di applicazione.

Ho risolto il problema disattivando la guardia originale nel costruttore della classe copia di base (così l'azione di distruttore non viene attivato per la configurazione per il quale il costruttore di copia viene chiamato), ma quello che mi preoccupa è:

è la copia-the-temporanea comportamento standard-compliant? Fa lo standard dice che il riferimento const dovrebbe puntare direttamente alla temperatura, o si tratta di un comportamento definito dall'implementazione non specificato nella norma?

Ho basato il mio codice più o meno sul campo di applicazione Articolo Guardia in GotW 88 l'articolo di DDJ e Herb Sutter, ma entrambe queste fonti non sembrano rispondere alla chiamata distruttore in precedenza in considerazione.

Tutte le informazioni da qualcuno più esperto sarà apprezzato.

EDIT:

Ok il codice è qualcosa di simile:

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;
È stato utile?

Soluzione

Entrambi i comportamenti sono gli standard conformi. Se si dispone di codice come questo:

T foo()
{
  return T();
}

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

Poi, concettualmente, in foo, viene creato un oggetto temporaneo. Questa temporanea viene copiato il ritorno del valore di foo. In main, la copia (che è anche un oggetto temporaneo) è destinato a x.
La copia che è il ritorno-valore dal foo prende il ciclo di vita esteso, ma non la temporanea che era la fonte per la copia.

Ma, lo standard C ++ permette in modo esplicito gli oggetti temporanei ridondanti da eliso. Così, invece di creare una temporanea e la copia che oltre nello slot per i valori di ritorno, foo può creare direttamente la temporanea in quello slot.
Entrambe le opzioni sono possibili, e il compilatore non ha nemmeno bisogno di documento quando usi l'opzione.

Le sezioni pertinenti del standard C ++ sono 6.6.3 ([stmt.return]) e 12.2 ([class.temporary]).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top