2016-07-26 34 views
-4

Der folgende Code verwendet eine Referenz von einem unique_ptr in einer Map, um ein Objekt zu füllen. Eine spätere Referenz von unique_ptr zeigt keine Spur der Updates.Wird beim Zurückgeben einer Referenz von einem unique_ptr manchmal eine Kopie des Objekts erstellt?

XSSFWorkbook :: CreateCellStyle ist ein Client für das XSSFCellStyle :: CreateCellStyle Fabrik-Funktion. Es speichert das XSSFCellStyle Objekt in UPTR__CellStylesMap und gibt einen Verweis darauf zurück.

XSSFWorkbook :: GetStylesheetXml() erhält später einen Verweis auf jeden XSSFCellStyle und verwendet es die XML-Ausgabe.

XSSFWorkbook.cpp

// **************************************************************************** 
// CreateCellStyle 
// **************************************************************************** 
    XSSFCellStyle& 
    XSSFWorkbook::CreateCellStyle() 
    { map<int, unique_ptr<XSSFCellStyle>>::iterator iter__CellStylesMap; 
     unique_ptr<XSSFCellStyle>      uptr__XSSFCellStyle  = nullptr; 

     uptr__XSSFCellStyle = XSSFCellStyle::CreateCellStyle(); 
     UPTR__CellStylesMap->insert(make_pair(UPTR__CellStylesMap->size(), move(uptr__XSSFCellStyle))); 
     iter__CellStylesMap = UPTR__CellStylesMap->find(UPTR__CellStylesMap->size() - 1); 
     return *iter__CellStylesMap->second 
    } 

// **************************************************************************** 
// GetStylesheetXml 
// **************************************************************************** 
    string 
    XSSFWorkbook::GetStylesheetXml() 
    { map<int, unique_ptr<XSSFCellStyle>>::iterator iter__CellStylesMap; 
     string           str___CellStyleXfsXml = ""; 

//  ======================================================================== 
//  Build the XML for the Cell Styles. 
//  ======================================================================== 
     if(UPTR__CellStylesMap->size() > 0) 
     { str___CellStyleXfsXml += "<cellStyleXfs count=\"" + ConvertToString(UPTR__CellStylesMap->size()) + "\">"; 
      iter__CellStylesMap  = UPTR__CellStylesMap->begin(); 
      while(iter__CellStylesMap != UPTR__CellStylesMap->end()) 
//   { str___CellStyleXfsXml   += iter__CellStylesMap->second->GetXml(); 
      { XSSFCellStyle& xssf__CellStyle = *iter__CellStylesMap->second; 
       str___CellStyleXfsXml   += xssf__CellStyle.GetXml(); 
       iter__CellStylesMap++; 
      } 
      str___CellStyleXfsXml += "</cellStyleXfs>"; 
... 
    } 

/ **************************************************************************** 
// GetXml 
// **************************************************************************** 
    string 
    XSSFWorkbook::GetXml() 
    { string str___WorkbookXml = ""; 

     str___WorkbookXml += "<workbook><sheets><sheet name=\"1\" sheetId=\"1\" r:id=\"rId1\" /></sheets></workbook>"; 
     str___WorkbookXml += GetStylesheetXml(); 
... 
     return str___WorkbookXml; 
    } 

Dieser Code in WinMain Anrufe XSSFWorkbook :: GetXml() die dann ruft XSSFWorkbook :: GetStylesheetXml() einen Verweis auf die XSSFCellStyle zu erhalten Objekt und drucken Sie seine XML.

XSSFCellStyle xssf__CellStyle = xssf__Workbook.CreateCellStyle(); 
xssf__CellStyle.SetApplyAlignment(true); 
uptr__OoxmlTester->SetOoxml(xssf__Workbook.GetXml()); 

Er kehrte die Standard im XSSFCellStyle eingestellten Werte :: XSSFCellStyle() Initialisierungsliste, obwohl cout Aussagen ergeben, dass XXSFCellStyle :: SetApplyAlignment() richtig die ApplyAlignment Eigenschaft festgelegt.

Aber mit dem XSSFCellStyle Referenz statt

uptr__OoxmlTester->SetOoxml(xssf__CellStyle.GetXml()); 

tat Rückkehr der aktualisierte Wert (natürlich).

Ändern XSSFWorkbook :: CreateCellStyle(), so dass es wieder ein Rohzeiger

XSSFCellStyle* 
XSSFWorkbook::CreateCellStyle() 
... 
return iter__CellStylesMap->second.get(); 

und WinMain ebenfalls

XSSFCellStyle* ptr___CellStyle = xssf__Workbook.CreateCellStyle(); 
ptr___CellStyle->SetApplyAlignment(true); 
uptr__OoxmlTester->SetOoxml(xssf__Workbook.GetXml()); 

retured die aktualisierten Werte, die zeigen, dass der Zeiger-Version tut Aktualisieren Sie tatsächlich die XSSFCellStyle Instanz in UPTR__CellStylesMap.

Ich sehe nicht, wie die Referenzversion von XSSFWorkbook :: CreateCellStyle() gibt mir einen Verweis auf ein XSSFCellStyle Objekt nicht in UPTR__CellStylesMap (eine Kopie?), Während der gleiche Code in XSSFWorkbook :: GetCellStyleXml()erhält erhalten einen Verweis auf XSSFCellStyle Objekt in UPTR__CellStylesMap.

Weil so etwas wie eine NULL gibt es keine XSSFCellStyle, habe ich die Referenzversion zugunsten der unique_ptr Version aufgegeben, aber ich würde noch gerne wissen, wie nie dieses Geheimnis neu zu erstellen.

P.S. Mein Codierungsstil bricht mit Konvention und stört manche Leute. Bitte lass dich nicht stören.

+6

Können Sie eine [MVCE] (http://stackoverflow.com/help/mcve) erstellen? Dies ist viel zu viel Code für das, was eine ziemlich präzise Frage sein sollte. – TartanLlama

+0

Wahr; Ich habe 6 Stunden dafür gebraucht. Ich werde bis zu diesem Wochenende keine Zeit haben, an einem MVCE zu arbeiten. – pbyhistorian

+0

Ich empfehle Ihnen [this] (https://www.youtube.com/watch?v=BiYliKliFvs) sprechen, wo sie unter anderem argumentieren, dass Kommentare wie '// GetXml' auf eine Methode namens' GetXml' nicht sind Nett überhaupt. – user463035818

Antwort

1

Ja Sie erstellen eine Kopie in dieser Zeile:

XSSFCellStyle xssf__CellStyle = xssf__Workbook.CreateCellStyle(); 

Es soll beachtet werden, dass die Kopie ist nicht, wie Sie angedeutet, erstellt durch den Verweis Rückkehr, sondern vielmehr durch einen neuen Wert mit der Initialisierung Referenz zurückgegeben.
Wenn Sie eine Kopie vermeiden möchten, sollten Sie das Ergebnis entweder in einer Referenz oder in einem Zeiger speichern.

XSSFCellStyle& xssf__CellStyle = xssf__Workbook.CreateCellStyle(); 
//or this 
XSSFCellStyle* ptr__CellStyle = &xssf__Workbook.CreateCellStyle(); 

Wenn Sie versehentlich das Kopieren vermeiden wollen, dann sollten Sie die Kopie-Konstruktor von XSSFCellStyle wie diese zu löschen betrachten:

XSSFCellStyle(const XSSFCellStyle&) = delete; 

Ich weiß, es ist eine stilistische Entscheidung, aber ich glaube nicht, dass ein Funktion beginnend mit Create sollte eine Referenz zurückgeben.

+0

Ich bin so nah dran. Es sieht so aus, als ob die Namenskonvention für eine Funktion, die eine Referenz zurückgibt, "get ...()" lautet. – pbyhistorian

+0

@pbyhistorian ja würde ich wahrscheinlich eine Referenz mit einem Accessor verbinden, aber in Ihrem Fall ist es notwendig zu kommunizieren, dass ein neues Objekt erstellt wird auch, so denke ich, "getNewXYZ()" ist, was mich am wenigsten überraschen würde. Aber darüber nachzudenken, Create ist nicht wirklich so schlimm. In jedem Fall ist das Dokumentieren des Besitzes (oder in diesem Fall des Fehlens davon)/Lebensdauer des zurückgegebenen Objektverweises (oder -zeigers) in der Funktionsdokumentation wahrscheinlich wichtiger als der Name. – PeterT