陷阱与生命周期
避免悬空视图
陷阱与生命周期 是 CoddyKit 上的免费 C++ Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 C++ Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 C++ Academy 课程共包含 4 节课。
视图不拥有数据
string_view 只指向由其他对象拥有的字符。如果那段存储消失,视图就会悬空,访问它会产生未定义行为。
从临时对象产生悬空视图
将视图绑定到临时的 std::string 很危险:临时对象会在语句末尾销毁,使视图指向已释放的内存。
#include <string>
#include <string_view>
std::string make() { return "temp"; }
int main() {
std::string_view sv = make(); // dangles immediately
// using sv here is undefined behavior
(void)sv;
}返回指向局部对象的视图
绝不要返回指向局部字符串内部的视图;函数返回时,局部字符串就会被销毁。
#include <string>
#include <string_view>
std::string_view bad() {
std::string local = "oops";
return local; // local dies, view dangles
}
int main() { (void)bad(); }安全情况:指向仍存活字符串的视图
只要源对象的生命周期长于视图,使用视图就是安全的。在这里,字符串会在整个函数期间保持存在。
#include <iostream>
#include <string>
#include <string_view>
int main() {
std::string s = "alive";
std::string_view sv = s;
std::cout << sv << "\n"; // safe
}不保证以空字符结尾
视图中的数据不保证以 \0 结尾。将 sv.data() 传给要求 C 字符串的 C 函数,可能会导致函数读取末尾之后的内容。
使用 size(),不要使用 strlen
请始终使用 sv.size() 获取长度,而不要依赖 C 字符串函数,因为视图可能只是较大缓冲区中的一段切片。
#include <iostream>
#include <string_view>
int main() {
std::string_view sv = std::string_view("hello world").substr(0, 5);
std::cout << sv.size() << "\n"; // 5, not 11
}修改源对象
如果底层字符串重新分配了内存(例如 push_back 导致容量增长),现有的指向其中的视图就会失效。
将视图存储为成员
将 string_view 存储为类成员时请务必谨慎;您必须保证被引用的数据生命周期长于对象。不确定时,请改为存储 std::string。
参数通常是安全的
将 string_view 用作函数参数是安全且符合惯用法的场景:实参的生命周期会长于这次调用。
#include <iostream>
#include <string_view>
size_t len(std::string_view sv) { return sv.size(); }
int main() {
std::cout << len("temporary is fine here") << "\n";
}必须持久保存时进行复制
如果您需要在源对象的生命周期结束后继续保留文本,请将其复制到 std::string 中。复制就是拥有数据所需付出的代价。
#include <string>
#include <string_view>
std::string keep(std::string_view sv) {
return std::string(sv); // owns a copy
}
int main() { (void)keep("persist"); }经验法则
参数和生命周期较短的局部对象优先使用 string_view。除非数据的生命周期明确更长,否则不要将它用作返回类型或长期存在的成员。
快速检查
检查您对视图生命周期的理解。
回顾
您学习了视图的陷阱和生命周期:
- 视图不拥有数据;源对象的生命周期必须长于视图。
- 避免让视图指向临时对象和局部对象。
- 视图不保证以空字符结尾,请使用
size()。 - 需要持久保存文本时,请将其复制到
std::string中。
常见问题解答
「陷阱与生命周期」课时是免费的吗?
是的 — 「陷阱与生命周期」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 C++ Academy 课程的其余内容,请升级到 CoddyKit PRO。 C++ Academy 课程共包含 4 节课。
「陷阱与生命周期」这节课中我会学到什么?
避免悬空视图 你通过在浏览器中直接运行的动手代码来练习 C++ Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 C++ Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 C++ Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。
「陷阱与生命周期」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 C++ Academy 课中编写并运行代码吗?
能。每节 C++ Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 为什么使用 string_view
- 创建视图
- 陷阱与生命周期
- 字符串算法