【发布时间】:2020-12-17 14:56:34
【问题描述】:
正如您可能从标题中猜到的那样,我想了解将 std::string 作为 const 引用传递给函数时究竟会发生什么,因为今天早些时候我遇到了一些我不太了解的情况完全。这是一些代码:
#include <string>
#include <stdio.h>
struct Interface {
virtual void String1(const std::string &s) = 0;
virtual void String2(const std::string &s) = 0;
virtual void DoSomething() = 0;
};
struct SomeClass : public Interface {
void String1(const std::string &s) override { s1 = s.c_str(); }
void String2(const std::string &s) override { s2 = s.c_str(); }
void DoSomething() override { printf("%s - %s\n", s1, s2); }
private:
const char *s1, *s2;
};
struct AnotherClass {
AnotherClass(Interface *interface) : interface(interface) {
this->interface->String1("Mean string literal");
}
void DoTheThing() {
std::string s("Friendlich string literal");
interface->String2(s);
interface->DoSomething();
}
private:
Interface *interface = nullptr;
};
int main(int argc, char **argv) {
SomeClass some_class;
AnotherClass another_class(&some_class);
another_class.DoTheThing();
}
当在 SomeClass 中对 s1 和 s2 使用 const char * 时,程序将打印 Friendlich 字符串文字 - Friendlich 字符串文字 或 [some rubbish] - Friendlich 字符串文字 而不是 平均字符串文字 - Friendlich 字符串文字 正如我所期望的那样。
当为 s1 和 s2 切换到 std::string 时,它按预期工作,打印 Mean string literal - Friendlich string literal。
我和同事的猜测是,AnotherClass 的 ctor 中的字符串超出了范围,但 SomeClass 由于 c_str() 仍然存储了字符串的地址。
当对 s1 和 s2 使用 std::string 而不是 const char * 时,它实际上会创建一个副本,因此超出范围不是问题。像这样:
struct SomeClass : public Interface {
void String1(const std::string &s) override { s1 = s; }
void String2(const std::string &s) override { s2 = s; }
void DoSomething() override { printf("%s - %s\n", s1.c_str(), s2.c_str()); }
private:
std::string s1, s2;
};
那么……到底发生了什么?为什么它不能与 const char * 一起使用?为什么它可以与 std::string 一起使用?
【问题讨论】: