[英]What happens when a string literal is passed to a function accepting a const std::string & in C++?
as you can probably guess from the title, I want to understand what exactly happens when a std::string is passed to a function as a const reference, because earlier today I ran into a few situations I didn't quite understand entirely.正如您可能从标题中猜到的那样,我想了解将 std::string 作为常量引用传递给函数时究竟会发生什么,因为今天早些时候我遇到了一些我不太完全理解的情况。 Here's some code:
这是一些代码:
#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();
}
When using const char * for s1 and s2 in SomeClass the program prints Friendlich string literal - Friendlich string literal or [some rubbish] - Friendlich string literal instead of Mean string literal - Friendlich string literal as I was expecting.当在 SomeClass 中对 s1 和 s2 使用 const char * 时,程序会打印Friendlich string literal - Friendlich string literal或[some rubbish] - Friendlich string literal而不是Mean string literal - Friendlich string literal,正如我所期待的。
When switching to std::string for s1 and s2 it works as expected, printing Mean string literal - Friendlich string literal .当为 s1 和 s2 切换到 std::string 时,它按预期工作,打印Mean string literal - Friendlich string literal 。
What a coworker and I are guessing is that the string in the ctor of AnotherClass goes out of scope but SomeClass still has the address of the string stored because of c_str().我和一位同事猜测,AnotherClass 的 ctor 中的字符串超出了范围,但由于 c_str(),SomeClass 仍然存储了字符串的地址。
When using std::string instead of const char * for s1 and s2 it actually makes a copy, so going out of scope isn't a problem.当对 s1 和 s2 使用 std::string 而不是 const char * 时,它实际上会创建一个副本,因此超出范围不是问题。 Like this:
像这样:
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;
};
So... what's really happening?那么……到底发生了什么? Why doesn't it work with const char *?
为什么它不适用于 const char *? Why does it work with std::string?
为什么它适用于 std::string?
When you pass a string literal to a function that accepts const std::string&
, the following events occur:当您将字符串文字传递给接受
const std::string&
的函数时,会发生以下事件:
const char*
const char*
std::string
object is created.std::string
对象。 Its internal buffer is allocated, and initialized by copying the data from the const char*
until the terminating null is seen.const char*
复制数据来初始化,直到看到终止的 null。 The parameter refers to this temporary object. If the c_str()
pointer is saved from the parameter, it becomes a dangling pointer after the temporary object is destroyed since it points into the temporary object's internal buffer.如果
c_str()
指针是从参数中保存的,那么在临时对象被销毁后它就变成了一个悬空指针,因为它指向临时对象的内部缓冲区。
A similar problem will occur if the function accepts std::string
.如果函数接受
std::string
也会出现类似的问题。 The std::string
object will be created when the function is called and destroyed when the function returns or soon afterward, so any saved c_str()
pointer will become dangling. std::string
对象将在函数被调用时创建并在函数返回时或不久之后销毁,因此任何保存的c_str()
指针都将变为悬空。
If the function accepts const std::string&
and the argument has type std::string
, however, no new object is created when the function is called.但是,如果函数接受
const std::string&
并且参数的类型为std::string
,则在调用函数时不会创建新对象。 The reference refers to the existing object.引用是指现有对象。 The
c_str()
pointer will remain valid until the original std::string
object is destroyed. c_str()
指针将保持有效,直到原始std::string
对象被销毁。
A char *
isn't an object, it's a pointer to characters that exist in some other context. char *
不是对象,它是指向存在于其他上下文中的字符的指针。 If you assign such a pointer to a temporary variable, or data contained within a temporary variable, it will be invalid when the temporary is destroyed.如果将这样的指针分配给临时变量或临时变量中包含的数据,则在销毁临时变量时它将无效。 Using it after that point produces undefined behavior.
在那之后使用它会产生未定义的行为。
When you have member variables of std::string
, a copy is made at the time of assignment so it doesn't matter if the temporary is destroyed or not.当您拥有
std::string
成员变量时,会在赋值时进行复制,因此临时对象是否被销毁并不重要。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.