在玩 c-strings 和 std::string 时,我遇到了一种奇怪的行为(我相信这只是对我很好奇,并且存在一个完全有效的 c++ 答案)。通常,当我将字符串传递给类的构造函数时,我会执行以下操作:
class Foo {
public:
Foo(const std::string& bar) bar_(bar) { }
private:
const std::string& bar_;
};
int main() {
Foo("Baz");
return 0;
}
到目前为止效果很好,我(也许是天真地?)从未质疑过这种方法。
然后最近我想实现一个简单的包含数据的类,当剥离到它的基本结构时,它看起来像这样:
#include <iostream>
#include <string>
class DataContainer {
public:
DataContainer(const std::string& name, const std::string& description)
: name_(name), description_(description) {}
auto getName() const -> std::string { return name_; }
auto getDescription() const -> std::string { return description_; }
private:
const std::string& name_;
const std::string& description_;
};
int main() {
auto dataContainer = DataContainer{"parameterName", "parameterDescription"};
auto name = dataContainer.getName();
auto description = dataContainer.getDescription();
std::cout << "name: " << name.c_str() << std::endl;
std::cout << "description: " << description.c_str() << std::endl;
}
输出是:
name: parameterName
description:
我*.c_str()
在这里使用它,因为这是我在实际代码库中使用它的方式(即使用 google 测试和EXPECT_STREQ(s1, s2)
.
当我在主函数中删除*.c_str()
时,我得到以下输出:
name: parameterName
description: tion
所以描述的原始字符串被截断,初始字符串丢失。我可以通过将类中的类型更改为:
private:
const std::string name_;
const std::string description_;
现在我得到了预期的输出
name: parameterName
description: parameterDescription
很好,我可以使用这个解决方案,但我想了解这里发生了什么。另外,如果我将主要功能稍微更改为
int main() {
auto dataContainer = DataContainer{"parameterName", "parameterDescription"};
auto name = dataContainer.getName().c_str();
auto description = dataContainer.getDescription().c_str();
std::cout << "name: " << name << std::endl;
std::cout << "description: " << description << std::endl;
}
我如何在类中存储字符串并不重要DataContainer
,即通过 const ref 或 value。在这两种情况下,我得到
name: parameterName
description:
以及关于clang的警告:
<source>:19:17: warning: object backing the pointer will be destroyed at the end of the full-expression [-Wdangling-gsl]
auto name = dataContainer.getName().c_str();
所以我猜这个问题是由 *.c_str() 本身引起的?但是,我不太明白为什么我不能通过 const ref 存储两个字符串名称和描述。任何人都可以对这个问题有所了解吗?