C++ 当作为QString返回时,在temp上使用c_str是否仍然会失败?

C++ 当作为QString返回时,在temp上使用c_str是否仍然会失败?,c++,qt,c++11,memory,qt5,C++,Qt,C++11,Memory,Qt5,我知道当错误地使用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,Qt5.5) 这是使用to_string函

我知道当错误地使用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,Qt5.5)

这是使用
to_string
函数的uuid类

它返回一个
std::string
。这是一个临时对象,我认为
c_str()
很危险

返回类型
QString
是否以某种方式改变了这一点?我不确定这是否意味着:

返回QString(to_string(_uuid).c_str())(我只是猜测)

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

问题:安全吗?或者在构建
QString
之前,temp是否已销毁?

来回答问题

安全吗?或者在构建
QString
之前,温度是否已销毁

它是安全的

正如前面提到的OP一样,
std::string::c_str()
的结果只有在相应的
std::string
保持不变(包括未删除)时才有效

函数必须返回
QString
,并且
返回
const char*
调用。 如果编译器发现从
const char*
QString
的转换,则编译器将接受它。 在某些条件下,它将:

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

编译应用程序时,可以通过从ASCII定义QT_NO_CAST_来禁用此构造函数。例如,如果希望确保所有用户可见的字符串都经过QObject::tr(),这将非常有用

因此,问题归结为:

返回到_string()
std::string
是否足够长,可以向
QString
的构造函数提供指向其内部原始字符串的指针

是的

发件人:

所有临时对象都将被销毁,这是计算(词汇上)包含创建它们的点的完整表达式的最后一步,如果创建了多个临时对象,它们将按照与创建顺序相反的顺序销毁。即使评估以抛出异常结束,这也是正确的

在本例中,完整表达式为
to_string(_uuid).c_str()
(即
返回之后和
之前的所有内容)


为了使其更加明确和健壮(例如,独立于是否定义了ASCII的
QT\u NO\u CAST\u),我将其写成:

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

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

来回答这个问题

安全吗?或者在构建
QString
之前,温度是否已销毁

它是安全的

正如前面提到的OP一样,
std::string::c_str()
的结果只有在相应的
std::string
保持不变(包括未删除)时才有效

函数必须返回
QString
,并且
返回
const char*
调用。 如果编译器发现从
const char*
QString
的转换,则编译器将接受它。 在某些条件下,它将:

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

编译应用程序时,可以通过从ASCII定义QT_NO_CAST_来禁用此构造函数。例如,如果希望确保所有用户可见的字符串都经过QObject::tr(),这将非常有用

因此,问题归结为:

返回到_string()
std::string
是否足够长,可以向
QString
的构造函数提供指向其内部原始字符串的指针

是的

发件人:

所有临时对象都将被销毁,这是计算(词汇上)包含创建它们的点的完整表达式的最后一步,如果创建了多个临时对象,它们将按照与创建顺序相反的顺序销毁。即使评估以抛出异常结束,这也是正确的

在本例中,完整表达式为
to_string(_uuid).c_str()
(即
返回之后和
之前的所有内容)


为了使其更加明确和健壮(例如,独立于是否定义了ASCII的
QT\u NO\u CAST\u),我将其写成:

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


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

代码的最小化版本是:

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
就被构造出来了。只有这样,您通过
c_str()
访问的
std::string
才会被销毁

return
在这里所做的工作如下:

QString toString(const boost::uuids::uuid &uuid)
{
  return QString(to_string(uuid).c_str());
}
同样:析构函数在对完整表达式求值后运行。完整表达式是
QString
构造函数调用。因此,临时
std::string
必须处于活动状态,直到
QString
完成构造

而这个
QString
结构总是一个副本。无论C字符串来自何处,它都会在转码到UTF-16时被复制。换句话说:拷贝不是比特
QString toString(const boost::uuids::uuid &uuid)
{
  return to_string(uuid).c_str();
}
QString toString(const boost::uuids::uuid &uuid)
{
  return QString(to_string(uuid).c_str());
}