Почему объект локали освобождает фасет, который не был создан им? - PullRequest
0 голосов
/ 15 мая 2019

Прошу прощения, я китаец с очень плохим знанием английского языка. Я надеюсь, что я правильно выражаю вещи.

Я не думаю, что необходимо освобождать объект, проверяя подсчет ссылок какого-либо типа в мире C ++. Я полагаю, что большинство программистов на c ++ считают RAII лучшим методом. Итак, почему std::facet был реализован STL, как эти? По историческим причинам (до C ++ 11)?

Как мы знаем, конструктор std :: numpunct получает параметр (size_t ref), который управляет уничтожением самого себя. Если "ref" равен 0, этот объект std :: numpunct будет освобожден автоматически. Я научился правильно кодировать его и реализовал Formater следующим образом.

struct GrouingDigits_T : std::numpunct<char> {
    GrouingDigits_T( char p_cDigits, size_t p_uiRef = 1 ) :
        std::numpunct<char>( p_uiRef ),
        m_iDigits( p_cDigits ) {};

    string do_grouping() const override {
        return string( 1, m_iDigits );
    };

    char m_iDigits = 4;
    /* yes, We Chinese people are prefer to read numbers grouped into
    4 digits. Sorry for my ugly English.*/
};

template<typename T>
inline std::string formatNumber( const T & p_Value,
                                 size_t   p_uiWidth = 0,
                                 size_t   p_uiPrec = 2,
                                 size_t   p_uiGroup = 4,
                                 char     p_cFill = ' ' ) {
    ostringstream oss;

    // solution1 likes the sample in cppreference:
    locale locGrpDigits(
        oss.getloc(),
        new GrouingDigits_T( static_cast<char>( p_uiGroup ), 0 ) );

    // solution2:
    GrouingDigits_T gd( static_cast<char>( p_uiGroup ), 1 );
    locale locGrpDigits( oss.getloc(), &gd );

    oss.imbue( locGrpDigits );

    oss << std::fixed
        << std::setw( p_uiWidth )
        << std::setprecision( p_uiPrec )
        << std::setfill( p_cFill )
        << p_Value;
    std::string strResult( oss.str() );

    if ( p_uiWidth > 0 && strResult.length() > p_uiWidth )
        return std::string( p_uiWidth, '*' );//too wide
    else
        return strResult;
};

Решение1 более вероятно приводит к утечке памяти или двойному освобождению, в то время как решение2 более безопасно, не так ли?

...