Frage

Ich habe eine Frage zu einigen C ++ Standard Compliance oder fehlt es.

In meinem Projekt verwende ich einige einfachen Schutz Klasse, die den konstanten Referenz Trick verwendet. Ich bin mit Visual Studio 2005 und es gibt zwei Konfigurationen -. Ein für die normale Release-Build und die zweiten für Unit-Tests

In beiden Fällen gibt es einige temporären hängen auf der konstanten Referenz am Ende, aber was in der Zwischenzeit passiert, ist das Problem. Für die Freigabe Konfiguration direkt die konstanten Referenz verweist auf die Temperatur in der Rückkehr der Hilfsfunktion Vorlage erstellt, die die Garde-Instanz erstellt (kein Copy-Konstruktor aufgerufen wird, nicht einmal was das betrifft instanziiert).

Aber für Unit-Test-conf der Funktionsvorlage Temperatur wird zunächst kopiert und dann der Destruktor aufgerufen wird, zu tun, was nur getan werden soll, nachdem die konstante Referenz des Bereichs geht aus.

Ich habe das Problem gelöst, indem die ursprüngliche Wache in Basisklasse Copykonstruktor deaktivieren (so die Aktion in destructor nicht für Config für die ausgelöst wird Copy-Konstruktor aufgerufen wird), aber was mich stört, ist:

Ist die Kopie-the-temporäres Verhalten Standard-konform? Ist der Standard sagt, dass der const Verweis auf die Temperatur direkt anweisen, oder ist diese Implementierung definierte Verhalten in der Norm nicht angegeben?

Ich habe meinen Code in etwa auf Scope-Schutz Artikel in DDJ und Herb Sutter GOTW 88 Artikel basiert, aber diese beiden Quellen scheinen nicht die frühere Destruktoraufrufs zu berücksichtigen.

Alle Informationen von jemandem mehr Wissen werden geschätzt.

EDIT:

Ok der Code ist so etwas wie folgt aus:

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;
War es hilfreich?

Lösung

Beide Verhaltensweisen sind konforme Standards. Wenn Sie Code wie folgt aussehen:

T foo()
{
  return T();
}

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

Dann konzeptionell in foo wird ein temporäres Objekt erstellt. Diese temporären wird den Rückgabewert von foo kopiert. In main, diese Kopie (die auch ein temporäres Objekt ist) an x gebunden.
Die Kopie, die der Rückgabewert von foo ist bekommt seine Lebensdauer verlängert, aber nicht die temporären, dass die Quelle für die Kopie war.

Aber der C ++ Standard erlaubt explizit redundante temporäre Objekte elided werden. Anstatt also eine temporäre Erstellen und Kopieren, dass mehr als in den Steckplatz für die Rückgabewerte können foo direkt die temporäre in diesem Slot erstellen.
Beide Optionen sind möglich, und der Compiler hat noch nicht einmal zu dokumentieren, wenn es verwendet wird, die Option.

Die entsprechenden Abschnitte der C ++ Standard sind 6.6.3 ([stmt.return]) und 12.2 ([class.temporary]).

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top