- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
考虑一个从返回 const std::string&
的方法或从空字符串返回 std::string_view
的方法。令我惊讶的是,以这种方式编写方法会导致悬空字符串 View :
const std::string& otherMethod();
std::string_view myMethod(bool bla) {
return bla ? otherMethod() : ""; // Dangling view!
}
似乎编译器首先将 otherMethod()
的结果的临时 std::string
拷贝放在堆栈上,然后返回此临时拷贝的 View 而不是仅仅返回引用的 View 。首先我想到了一个编译器错误,但是 G++ 和 clang 都这样做了。
修复很简单:将 otherMethod
包装到 string_view
的显式构造中即可解决问题:
std::string_view myMethod(bool bla) {
return bla ? std::string_view(otherMethod()) : ""; // Works as intended!
}
为什么会这样?为什么原始代码会在没有警告的情况下创建隐式拷贝?
最佳答案
因为条件运算符就是这样工作的。
您在两个操作数上调用 ?:
,其中一个是 std::string const
类型的左值,另一个是 类型的左值>char const[1]
。条件运算符的语言规则......真的很复杂。 relevant rule是:
Otherwise, if the second and third operand have different types and either has (possibly cv-qualified) class type, or if both are glvalues of the same value category and the same type except for cv-qualification, an attempt is made to form an implicit conversion sequence from each of those operands to the type of the other. [ Note: Properties such as access, whether an operand is a bit-field, or whether a conversion function is deleted are ignored for that determination. — end note ] Attempts are made to form an implicit conversion sequence from an operand expression
E1
of typeT1
to a target type related to the typeT2
of the operand expressionE2
as follows:
- If E2 is an lvalue, the target type is “lvalue reference to
T2
”, subject to the constraint that in the conversion the reference must bind directly ([dcl.init.ref]) to a glvalue.- If E2 is an xvalue, [...]
If E2 is a prvalue or if neither of the conversion sequences above can be formed and at least one of the operands has (possibly cv-qualified) class type:
- if
T1
andT2
are the same class type [...]- otherwise, if
T2
is a base class ofT1
, [...]- otherwise, the target type is the type that E2 would have after applying the lvalue-to-rvalue, array-to-pointer, and function-to-pointer standard conversions.
Using this process, it is determined whether an implicit conversion sequence can be formed from the second operand to the target type determined for the third operand, and vice versa. If both sequences can be formed, or one can be formed but it is the ambiguous conversion sequence, the program is ill-formed. If no conversion sequence can be formed, the operands are left unchanged and further checking is performed as described below. Otherwise, if exactly one conversion sequence can be formed, that conversion is applied to the chosen operand and the converted operand is used in place of the original operand for the remainder of this subclause. [ Note: The conversion might be ill-formed even if an implicit conversion sequence could be formed. — end note ]
无法将 std::string const
转换为 char const(&)[1]
或 char const*
,但您可以将 char const[1]
转换为 std::string const
(内部嵌套的子弹)......这就是你得到的。 std::string const
类型的纯右值。也就是说,您要么复制一个字符串,要么构建一个新字符串……无论哪种方式,您都将 string_view
返回到一个立即超出范围的临时对象。
你想要的就是你所拥有的:
std::string_view myMethod(bool bla) {
return bla ? std::string_view(otherMethod()) : "";
}
或:
std::string_view myMethod(bool bla) {
return bla ? otherMethod() : ""sv;
}
条件运算符的结果是 string_view
,两种转换都是安全的。
关于c++ - 为什么 std::string_view 在三元表达式中创建悬空 View ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56634198/
我遵循了 V. Romeo 关于实体管理的教程(在 GitHub 和 Youtube 上)。 然后我尝试重写类 CEntity、CComponent 和测试 CPosition(主要来自 Romeo
为什么下面的代码中有悬空引用?我认为对 const 的引用总是将临时对象的生命周期延长到它们的范围。 boost::filesystem::recursive_directory_iterator i
我有一个多线程应用程序,将传入消息发布到 rabbitmq 交换。使用 rabbitmq java 客户端,我在应用程序启动时创建了一个 rabbitmq 连接,并在我的所有线程中共享它。每个线程都会
我有一个 Git 存储库,其中有大量提交不在特定分支下,我可以 git show 它们,但是当我尝试列出包含它们的分支时,它没有返回任何内容。 我认为这是悬空提交/树问题(由于 -D 分支),所以我修
我是 Linux 的新手,并且继承了保持我们的单一 Linux 服务器运行的职责。这是我们的SVN服务器,所以比较重要。 原来在我之前维护它的人有一个 cron 任务,当有太多 svnserve 进程
我是一名优秀的程序员,十分优秀!