C++中何时返回const char*而不是std::string

7
在下面的类中,speak() 返回 const char* 而不是 std::string,这样做有什么好处或原因吗?
class Animal
{
protected:
    std::string m_name;

    Animal(std::string name)
    : m_name(name)
    {
    }

public:
    std::string getName() { return m_name; }
    const char* speak() { return "???"; }
};

6
返回字符串字面量的指针时,不会创建新的字符串副本。如果返回std::string类型则需要进行内存复制。 - PeterT
像往常一样:它取决于情况。 - StoryTeller - Unslander Monica
3
与使用C语言编写的库进行交互时,您需要使用 const char*。例如,通过 MPI 库发送字符串。 - Daniel Langr
我认为如果你已经有了一个std::string,则永远不要返回const char*。返回const std::string&,并让调用者决定是否需要该const std::string&或从中派生的const char* - Galik
3
@Galik通过引用返回在许多情况下并不合适,而且相当危险。个人建议原帖作者只需通过复制返回一个std::string。编译器进行了很多优化。 - Kakalokia
显示剩余2条评论
3个回答

5

字符串字面值比如 "???" 的作用是告诉编译器在全局内存中包含特定顺序的字符 (加上结尾的字符 '\0')。字符串字面值表达式的类型是 const char*,指向该全局内存块。

也就是说,在这一 非常特殊的情况下,传递指针是安全的。请注意以下函数:

std::string speak() { return "???"; }

该函数体相同,但代码路径不同。字符串字面表达式(全局内存、指针)仍然存在,但它被用作 std::string 的构造函数的参数;它会被隐式转换为 std::string
因此,在这种非常特殊的情况下,当你只有一个字符串字面量时,你可以返回 const char*。当传递给另一个需要的函数时,它可能会被隐式转换为 std::string,所以 const char* 并没有那么多的优化。该 std::string 构造函数会动态分配一些内存(对于短字符串优化,可能不会),并从你提供的指针中进行复制。

2
自C++17起,还有另一个选项,即返回std::string_view。这也不会分配内存,并且将提供编译时字符串的长度。这应该是首选的变体,因为这也告诉调用者字符串有正确的边界,普通的char*可能指向未零结尾的内容或包含多个零字节的字符串。 - Norbert Lange

5

std::string带有很多可能不需要和未使用的功能。如果您不想要所有这些功能,应考虑使用成本。传递std::string至少需要将文字复制到字符串的内部存储中。如果将字符串传递给其他函数并返回,则可能会获得一些额外的副本。如果存在小字符串优化,则无法简单地移动字符串,因此在该情况下成本变得更高。

如果您不想承担成本,但又需要常量字符串的所有功能,请看一下std::string_view。实现通常仅包含指向基础数据的指针和大小值。因此,它的成本较低且具有丰富的功能。

实际上,如果符合您的需求,则传递const char*是完全没有问题的。

对于常量字符串,始终使用std::string是一个非常常见的模式,但不是一个好模式。


1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接