【问题标题】:Converting Date to const char*将日期转换为 const char*
【发布时间】:2014-03-26 17:37:11
【问题描述】:

我创建了一个Date 类,我正在尝试创建一个转换方法,以便您可以将Date 对象转换为const char*“字符串”。必须是const char*不是 string

但是,我发现了一些我无法解决的问题。

这是我的方法:

Date::operator char*() const {
    tm date = { 0, 0, 0, day_, month_ - 1, year_ - 1900, 0, 0, -1 };
    mktime(&date);

    char* weekday[] = { "sunday", ..., "saturday" };
    char* month[] = { "january", ..., "diciembre" };

    char string[50];
    sprintf(string, "%s %d / %s / %d", weekday[fch.tm_wday], day_, month[fch.tm_mon], year_);

    return string;
}

编译器说:

warning: address of local variable ‘cadena’ returned [-Wreturn-local-addr]
  char string[50];

如果我为字符串变量添加static 标签,它将被共享,我不希望这样。

我该怎么做?

【问题讨论】:

  • 您已将您的问题标记为“c++”,而不是“c”。有什么特殊原因不想使用std::string
  • 是的,它必须是 const char*,而不是字符串。
  • 您必须意识到char const* 不是字符串类型。它只是一个指针。你可以用指针做事——但是你需要定义一个内存管理的契约。一种方法可能是分配动态内存并将缓冲区返回给调用者;然后调用者将负责删除它。另一种方法是让调用者提供一个缓冲区供你填充。
  • 您可以将char string[50] 从您的方法中移出并使其成为该类的私有成员...但是如果您修改该实例的日期,它的内容仍然可能会发生变化。为什么不能返回std::string 并在之后从中获取const char *
  • 我试图这样做。我尝试创建一个char* string 属性,然后在调用该方法时动态保留内存,但出现错误。所以我在方法中声明了一个局部变量,并在那里动态分配它。现在它起作用了。每个人都在提到string,这让我发疯。我不能用!!!我被要求不要。我知道只要有string,生活就会很精彩。

标签: c++ casting type-conversion


【解决方案1】:

在类级别定义您的缓冲区,并在写入后从您的方法中返回它。

但请记住,这是一种愚蠢的工作方式,因为 (1) 对该方法的后续调用会改变缓冲区,如果之前的调用者仍然保留该指针,则会影响他们,以及 (2) 因为它违反了单一责任原则- 最后格式化操作的细节在逻辑上根本不属于日期类的状态。此外,缓冲区必须标记为 mutable 才能从您的 const 方法进行修改,这清楚地表明您违反了类的预期职责。

另外,“经典 C”方法将更改方法以从调用者接收缓冲区(连同其大小),然后直接写入其中。这将内存管理的负担转移到调用者(它在逻辑上属于哪里),但使使用该方法的语法变得相当繁重。

这两种方法都很笨拙和/或功能欠佳;我什至不会提到返回指向动态分配内存的指针的可能性,因为它具有与std::string 相同的开销,但没有自动内存管理(因此它绝对是最愚蠢的选择)。

正如在其他地方已经说过的,正确的 C++ 方法是返回一个std::string,它自己处理分配内存的生命周期。除非您处于极其特殊的条件下,否则没有理由不使用它。

【讨论】:

    【解决方案2】:

    您在函数内部创建了一个名为 string 的变量,一旦函数返回,该变量将超出范围(即变为无效引用)。您还返回了一个指向它的指针,这意味着您正在引用一个不再有效的内存区域。

    考虑返回一个std::string,它会为您自动管理内存。

    编辑:如果不这样做,您始终可以拥有一个 static 数组并返回一个指向它的指针。

    Date::operator const char*() const
    {
        static char str[50];
        // fill in array
        return str;
    }
    

    当然,您现在不能执行以下操作:

    Date d1{...};
    Date d2{...};
    
    const char* d1_str = s1;
    const char* d2_str = s2;
    

    因为用于将日期转换为字符串的数组由该类的所有实例共享。

    【讨论】:

    • 我不想使用string,我知道有人会这样说。我想创建一个到const char*的转换方法。
    • 很明显有人会这么说,因为使用 C++ 字符串(或类似的东西)是最明智的选择。在所有其他情况下,您必须在类本地拥有一个缓冲区(这意味着先前返回的值将在每次新调用时更改内容)或返回分配有 new 的内存,这与 std::string 的开销相同,但没有它细节(特别是自动生命周期管理)。
    • 我说我不想使用静态标签,因为它会被共享。
    • @dabadaba 剩下的就是动态分配内存并返回一个指向它的指针,希望用户调用delete。不过,这不是最干净的事情。
    • @dabadaba 好吧,转换运算符是const,所以你必须使string_aux mutable。这种情况越来越糟。帮自己一个忙:返回std::string
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-05
    • 1970-01-01
    • 1970-01-01
    • 2013-12-31
    相关资源
    最近更新 更多