代码之家  ›  专栏  ›  技术社区  ›  Alexey Malistov

函数返回后,指向字符串文本的指针是否仍然有效?

  •  16
  • Alexey Malistov  · 技术社区  · 16 年前

    以下函数返回的指针是否有效?

    const char * bool2str( bool flg )
    {
        return flg ? "Yes" : "No";
    }
    

    它在VisualC++和G++中运行良好。C++标准对此有何看法?

    4 回复  |  直到 16 年前
        1
  •  25
  •   dirkgently    16 年前

    储存时间:

    2.3.4 普通字符串文本和UTF-8字符串文本也被称为窄字符串文本。狭隘 字符串文字具有n const char__的__数组类型,其中n是下面定义的字符串大小,并且具有 静态存储时间

    结合3.7.1阅读

    3.7.1

    所有没有动态存储持续时间、没有线程存储持续时间的对象,并且 非本地具有静态存储持续时间。储存这些物品的时间应为 程序(3.6.2、3.6.3)。

    类型:

    附件C

    第2.13.4款:

    变化 :字符串文本生成常量 字符串文字的类型从char__的__数组更改为const char的__数组。__ char16_t string literal从某个整数类型的_数组更改为const char16_t._数组 char32_t string文本的类型从某个整型的_数组更改为常量char32的__数组。_- T._157;宽字符串文字的类型从wchar__的__数组更改为const wchar__的__数组。

    理论基础: 这样可以避免调用不适当的重载函数,因为它可能期望能够 修改它的参数。

    对原始特征的影响: 更改为定义良好的特性的语义。 转换困难:简单的句法转换,因为字符串文字可以转换为 ch*;(4.2)。最常见的情况是由新的但已弃用的标准转换处理的: CHAR*P=“ABC”;//在C中有效,在C++中被弃用 char*q=expr?“ABC::“de”;//在C中有效,在C++中无效

    使用范围: 有正当理由将字符串文本视为潜在指针的程序 可修改的内存可能很少。

    动态分配(在标准内存区域afaik的上下文中从不使用“heap”一词)内存需要一个函数调用,该调用最早可以发生 main 在分配静态内存之后。

        2
  •  13
  •   JSBÕ±Õ¸Õ£Õ¹    16 年前

    此代码完全有效且一致。唯一的“gotcha”是确保调用者不会尝试释放字符串。

        3
  •  12
  •   KeatsPeeks    16 年前

    此代码有效且符合标准。

    字符串文本存储在只读内存中,函数只获取所选字符串的地址。

    C++标准(2.134)表示:

    普通字符串文本具有类型 _ n const char_和static的数组 储存时间

    在这里,理解您的问题的关键是静态存储持续时间:字符串文本在程序启动时分配,并在程序持续时间内分配。您的函数只是获取地址并返回它。

        4
  •  5
  •   Loki Astari    16 年前

    技术上是的,它是有效的。
    字符串具有静态存储期限。

    但事实并非如此。

    这些是C字符串。C库和函数中的约定是返回应该释放的动态分配字符串。IE返回的指针隐式地将所有权传递回调用方(通常在C中也有例外)。

    如果您不遵循这些约定,您将使许多有经验的C-Developers感到困惑,他们可能会期望这个约定。如果您不遵循这个标准期望,那么应该在代码中很好地记录它。

    这也是C++(按你的标签)。因此,返回std::string更为传统。原因是,通过指针传递所有权只是隐含的(如果上述期望被打破但被记录,那么这会导致C代码中出现很多错误,不幸的是,代码的用户从未读取过documentaiton)。通过使用std::string,您传递的是一个对象,它们不再是任何所有权问题(结果作为一个值传回,因此是您的),但是因为它是一个对象,所以没有问题或资源分配问题。

    如果你担心效率,我认为这是一个错误的担心。

    如果要通过流进行打印,已经有了一个标准约定:

    std::cout << std::boolalpha << false << std::endl;
    std::cout << std::boolalpha << true  << std::endl;