从unique_ptr返回引用有时会创建其对象的副本吗?

时间:2016-07-26 08:28:24

标签: c++ dictionary reference copy-constructor unique-ptr

下面的代码使用地图中unique_ptr的引用来填充对象。来自unique_ptr的后续引用不会显示更新的痕迹。

XSSFWorkbook :: CreateCellStyle XSSFCellStyle :: CreateCellStyle 工厂函数的客户端。它将 XSSFCellStyle 对象存储在 UPTR__CellStylesMap 中,并返回对它的引用。

XSSFWorkbook :: GetStylesheetXml()稍后获取对每个 XSSFCellStyle 的引用,并使用它来输出XML。

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;
    }

WinMain 中的此代码调用 XSSFWorkbook :: GetXml(),然后调用 XSSFWorkbook :: GetStylesheetXml()以获取对 XSSFCellStyle 对象并打印其XML。

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

它返回了 XSSFCellStyle :: XSSFCellStyle()初始化列表中设置的默认值,即使cout语句显示 XXSFCellStyle :: SetApplyAlignment()设置了ApplyAlignment属性正常。

但是使用 XSSFCellStyle 引用

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

返回更新后的值(当然)。

更改 XSSFWorkbook :: CreateCellStyle(),以便返回原始指针

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

WinMain 同样

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

修复了更新的值,显示指针版本确实更新了 UPTR__CellStylesMap 中的 XSSFCellStyle 实例。

我不知道 XSSFWorkbook :: CreateCellStyle()的参考版本如何为我提供 XSSFCellStyle 对象的引用,而不是 UPTR__CellStylesMap < / strong>(副本?),而 XSSFWorkbook :: GetCellStyleXml() 中的相同代码获取对 XSSFCellStyle 对象的引用的 UPTR__CellStylesMap

因为没有NULL XSSFCellStyle 这样的东西,我已经放弃了引用版本而转而使用unique_ptr版本,但是我仍然想知道如何永远不会重新创造这个谜。

P.S。我的编码风格打破常规,让一些人感到不安。请不要让它打扰你。

1 个答案:

答案 0 :(得分:2)

是的,您正在此行中创建副本:

XSSFCellStyle xssf__CellStyle = xssf__Workbook.CreateCellStyle();

应该注意的是,正如您暗示的那样,副本不是通过返回引用来创建的,而是通过使用返回的引用初始化新值。
如果要避免复制,则应将结果存储在引用或指针中。

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

如果您想避免意外复制,那么您应该考虑删除XSSFCellStyle的复制构造函数,如下所示:

XSSFCellStyle( const XSSFCellStyle&) = delete;

我知道这是一个风格决定,但我不认为以Create开头的函数应该返回参考。