谁负责删除分面

Who is responsible for deleting the facet?

本文关键字:删除      更新时间:2023-10-16

我有一个函数,它使用 Boost.DateTime 库来生成当前的 GMT/UTC 日期和时间字符串(实时示例(。

std::string get_curr_date() {
    auto date = boost::date_time::second_clock<boost::posix_time::ptime>::universal_time();
    boost::posix_time::time_facet* facet = new boost::posix_time::time_facet("%a, %d %b %Y %H:%M:%S GMT");
    std::ostringstream os;
    os.imbue(std::locale(os.getloc(), facet));
    os << date;
    return os.str();
}

这主要基于 Boost.DateTime 的示例:

//example to customize output to be "LongWeekday LongMonthname day, year"
//                                  "%A %b %d, %Y"
date d(2005,Jun,25);
date_facet* facet(new date_facet("%A %B %d, %Y"));
std::cout.imbue(std::locale(std::cout.getloc(), facet));
std::cout << d << std::endl;
// "Saturday June 25, 2005"

我的代码运行良好,但现在我感到不安,因为这些特定的行包含new

  • boost::posix_time::time_facet* facet = new boost::posix_time::time_facet("%a, %d %b %Y %H:%M:%S GMT");

  • date_facet* facet(new date_facet("%A %B %d, %Y"));

如您所见,Boost.DateTime中没有delete,因此我不知何故认为我必须delete date_facet。我用std::unique_ptr来包装new time_facet对象。

std::unique_ptr<boost::posix_time::time_facet> facet(new boost::posix_time::time_facet("%a, %d %b %Y %H:%M:%S GMT"));

但是,正如您在此处看到的那样,我遇到了段错误错误。我也尝试手动delete new ed指针,但仍然收到相同的错误(抱歉,无法在 Koliru 中重现错误(。

time_facet指针在构造std::locale对象时作为参数传递,所以我很困惑谁是负责delete分面的人。

所以这是我问题的核心:

  • 我是否需要delete time_facet,还是std::locale对象负责delete它?

请注意,boost::posix_time::time_facet派生自boost::date_time::date_facet,而又派生自std::locale::facet。这个问题可以推广到std::locale::facet,尽管我的问题特定于time_facet

以下是一些关于std::locale构造函数的文档:

  • MSDN
  • cppreference.com

我是否需要删除time_facet还是 std::locale 对象 负责删除它?

您不需要删除time_facet,只要time_facet派生自 std::locale::facet ,它应该这样做。std::locale::facet是一个基类,所有方面都应派生自该基类,以实现引用计数的形式。该标准是这样说的:

§ 22.3.1.6

通过调用从区域设置对象获取分面引用后 use_facet<>,该引用仍然可用,并且来自 它的成员函数可以被缓存和重用,只要一些 区域设置对象引用该方面。

一旦不使用分面的所有引用,std::locale 的析构函数将管理和删除对分面的引用(如果其引用计数为 0(。

这在 C++11 标准的 §22.3.1.1.2 中都有规定。其中指出:

构造函数的 refs 参数用于生存期管理。

— 对于refs == 0,实现执行delete static_cast<locale::facet*>(f)(其中 f 是指向分面的指针( 当包含分面的最后一个区域设置对象被销毁时;为 refs == 1,实现永远不会破坏分面。

没有回答你的问题,因为其他人已经这样做了。但是,实际上不需要每次都构造区域设置。

std::string get_curr_date_time() {
    namespace bpt = boost::posix_time;
    namespace bdt = boost::date_time;
    std::ostringstream os;
    auto date = bdt::second_clock<bpt::ptime>::universal_time();
    const static std::locale currlocale (os.getloc(), new bpt::time_facet("%Y%m%d%H%M%S"));
    boost::posix_time::time_facet* facet = new boost::posix_time::time_facet("%a, %d %b %Y %H:%M:%S GMT");
    os.imbue(currlocale);
    os << date;
    return os.str();
}

区域设置负责删除分面。