【发布时间】:2021-09-06 00:28:36
【问题描述】:
我想用自定义类型做与std::quote 相同的事情,但我想错过使用这种带有临时右值的 API。在与std::quoted 一番交流后,我发现了以下问题:
为了高效std::quoted 强制存储 const 引用或指针以避免源对象的深拷贝,但没有机制可以避免存储引用的结果。如果我们存储它,然后删除源对象,最后将我们尝试访问的存储结果流式传输到已删除的引用或指针。
下面的例子试图说明问题:
#include <string>
#include <iostream>
#include <iomanip>
class String
{
public:
explicit String(const std::string & s) : _s(s) {std::cout << "String\n";}
~String() { std::cout << "~String\n"; _s = "ERROR TRY ACCESS DELETED STRING";}
const std::string & getS() const {return _s;}
private:
std::string _s;
};
int main()
{
std::cout << std::quoted(String("test").getS()) << '\n';
std::cout << '\n';
auto q = std::quoted(String("test").getS());
std::cout << q << '\n';
return 0;
}
这个例子打印:
String
"test"
~String
String
~String
"p DELETED STRING"
我们可以在 gcc(trunk) 和 clang(trunk) 中看到同样的问题。
【问题讨论】:
-
理解和管理对象的生命周期是程序员的任务。 C++ 为您提供了所有可能犯错和自取其辱的可能性。指导口号通常是“不要为你不需要的东西买单”。性能高于安全。正确使用它是你的工作。
-
auto q = std::string("text").c_str(); std::cout << q << '\n';会遇到同样的问题。临时对象消失了,任何指向其内容的东西都变得无效。