在temp上使用c_str,当返回为QString时还会失败吗?

问题描述 投票:0回答:1

我知道当错误地使用c_str时,指针会悬空,就像这样。

const char* str_ptr = functionReturningString().c_str();
// str_ptr is invalid, as the returned string from the function was temporary, and c_str simply points to that array.

我想知道这是否还适用于这段代码(C++11, Qt 5.5)

 QString UUId::toString () const
 {
    return to_string (_uuid).c_str();
 }

这是在使用 to_string 功能 助推的uuid类。

它返回一个 std::string. 这是个临时对象,我希望 c_str() 是危险的。

返回类型是否为 QString 以某种方式改变这一点?我不知道这是否真的会意味着。

return QString(to_string (_uuid).c_str()); (我只是猜测)

它应该会创建一个副本(如果你看一看 QString (const char *) 构造函数),如果我没有弄错的话。

疑问: 安全吗?或者说,临时工在被破坏之前 QString 是构造的?

c++ qt c++11 memory qt5
1个回答
1
投票

回答这个问题

它是安全的吗?还是说,临时工被破坏之前 QString 是构建?

QString UUId::toString () const
 {
    return to_string (_uuid).c_str();
 }

它是 安全的.

正如上文中所提到的,结果是 std::string::c_str() 是有效的,只有当相应的 std::string 是不变的(其中包括未删除)。

函数必须返回一个 QStringreturn 被称为 const char*.编译器会接受它,如果它发现从 const char*QString.在某些条件下会。

Qstring::QString(const char *str)

构造一个用8位字符串str初始化的字符串。给定的const char指针使用fromUtf8()函数转换为Unicode。

你可以在编译应用程序时定义QT_NO_CAST_FROM_ASCII来禁用这个构造函数。例如,如果你想确保所有用户可见的字符串都经过QObject::tr(),这就很有用。

所以,问题归结为。

是否 std::string 回来的 to_string() 活到足以养活建造者 QString 用指向其内部原始字符串的指针?

是的。

cppreference - 临时对象寿命:

所有临时对象在评价(词法上)包含创建点的全表达式的最后一步被销毁,如果创建了多个临时对象,则按照与创建顺序相反的顺序销毁。即使该评估以抛出异常结束,也是如此。

完整的表达式在这种情况下是 to_string (_uuid).c_str() 后的一切 return 而之前 ;).


为了使这一点更加明确和稳健(例如,独立于是否是 QT_NO_CAST_FROM_ASCII 是否被定义),我会把它写成。

QString UUId::toString() const
{
  return QString::fromUtf8(to_string(_uuid).c_str());
}

但是

QString UUId::toString() const
{
  return QString::fromStdString(to_string(_uuid));
}

应该是相当等价的,因为这将假定传递的参数的内容也是UTF-8编码的。(QString::fromStdString())


1
投票

你的代码的最小化版本是。

QString toString(const boost::uuids::uuid &uuid)
{
  return to_string(uuid).c_str();
}

这是安全的,因为你使用的是 c_str() 只是为了初始化一个 QString. QString 将C字符串视为UTF-8,并通过从UTF-8转码到UTF-16来初始化其内部UTF-16存储。当然,这将复制所有数据,所以当返回的完整表达式完成评估时,这个字符串的 QString 是构建。只有这样才是 std::string 您通过 c_str() 销毁。

ぐ或 return 这里的做法其实如下。

QString toString(const boost::uuids::uuid &uuid)
{
  return QString(to_string(uuid).c_str());
}

再一次:destructors运行 之后 完整的表达式已经被评估完整的表达式是 QString 构造函数的调用。所以,临时的 std::string 必须活着,直到 QString 完成建设。

而这 QString 建设是 始终 一个副本。无论C字符串来自哪里,在转码为UTF-16时都会被复制。换句话说:这个拷贝不是位相同的,而是Unicode码点相同的。它的结果是将C字符串中UTF-8编码所代表的Unicode码点用UTF-16表示。码点可以看作是32位的整数,在某种程度上简化了。

© www.soinside.com 2019 - 2024. All rights reserved.