- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
让我们考虑以下不正确的代码:
#include <string>
#include <iostream>
struct C {
C(const std::string &_s): s(_s) { }
void run() {
std::cout << "Here we are using the string " << s << "\n";
}
const std::string &s;
};
int main() {
C a("/tmp/example.log");
a.run();
return 0;
}
无论是 g++ 6.3.0 还是 clang 3.8.1 都会在没有警告的情况下编译这段代码,即使使用 -W -Wall -Werror
,但即使对于粗心的程序员来说,行为也只是说明这里有问题:
Here we are using the string Here we are usin
为什么结果并不像人们天真地期望的那样?从 const char *
创建的 std::string
对象的生命周期仅限于构造函数的范围。因此,当 foo()
构造函数返回时,foo::s
字段引用了不存在的对象。轰隆隆。
如果有人理解这个想法,就很容易介绍修复方法。它可以是显式创建 std::string
对象并将其作为参数传递:
std::string s("/tmp/example.log");
C a(s);
另一个我认为更安全的方法是将 foo::s
字段声明更改为:
const std::string s;
制作参数的本地不可修改拷贝,但它增加了复制对象的成本。好吧,在这个例子中,std::string 的复制不会自动导致深拷贝,但对于自己实现的类来说,这可能是完全不同的事情。
对于 C++11,几乎没有其他方法可用,如 this answer 中所述,但是 - 例如 - 在嵌入式 Linux 环境中,当您坚持使用旧编译器和一些遗留代码时,它不一定是一个不错的选择。
但是,无论程序员选择何种解决方案,都必须知道存在问题。即使我正确地编写了我的代码,我也愚蠢地假设编译器会足够聪明地检测到这种明显危险的情况,如果其他开发人员会落入传递 const char *
参数的陷阱。然而,我决定编写一些代码来检查编译器的行为,但我很失望——人们很容易陷入引用已经不存在的对象的陷阱。
将临时对象作为 const 引用传递是一种公认的危险,它已在 C++11 中以某种方式得到解决,但仍将责任转嫁给程序员以积极抵制这种行为。那么,期望编译器发出警告是否合理,或者应该依赖外部静态分析工具?
最佳答案
临时绑定(bind)到 const 引用作品,不应发出任何警告。它不是您代码中问题的根源。问题是您使用 const 引用作为成员而不是管理它的正确性。即使您按照您的建议传递 std::string
,也不会消除问题 - 该字符串必须比您的对象长寿才能使您的程序正确。将成员创建为 std::string
或 const std::string
不仅更安全,而且在这种情况下是安全且正确的方法。在某些情况下,您可能希望将 const 或非 const 引用存储为成员,但您必须了解自己在做什么并确保该引用不会悬空。编译器不太可能检测到极端情况并在这种情况下向您发出警告。
关于c++ - 在 const ref 类型参数上使用临时对象时,编译器是否应该警告不安全行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44568318/
你好,我正在尝试在 opensuse 中创建一个 Shell 脚本来创建 MySqlUsers,但是当我尝试运行它时,我得到了这个错误: Warning: Could not start progra
我阅读了有关此错误的所有信息,但未能找到任何解决方案。 我有一个看起来像这样的简单页面: $xmlfile = "/var/www/marees.xml"; //Fichier dans lequel
运行 Websphere App 服务器 V8.5 Liberty Profile。我找不到任何可以解决这些警告的帮助。我在 eclipse 。 ************** He
我尝试在 GC AppEngine 上部署应用程序。部署过程中没有错误,但应用程序无法运行(仅显示加载页面)。日志中唯一一个奇怪的原始 OpenBLAS WARNING - could not det
我刚开始学习 RestKit。我正在尝试使用它来使用 Foursquare api 获取附近的 field 。但每次我尝试“objectLoader:(RKObjectLoader *)objectL
我对 Vuejs 比较陌生,每次按键时都会收到以下警告: [Vue warn]: $attrs is readonly. found in ---> at src\component
Warning: simplexml_load_file() [function.simplexml-load-file]: I/O warning : failed to load external
我在尝试修改某些表时不断收到此错误。这是我的代码: /** = 1){ //$this->mysqli->autocommit(FALSE); //insert th
当我尝试使用 PHP 的 ftp_put 函数上传文件时,早些时候出现错误: 警告:ftp_put() [function.ftp-put]:无数据连接 现在,我尝试开启被动模式: ftp_pasv(
我一直在努力让这段代码适用于现阶段的年龄。它旨在计算一个范围内的素数,我已经编写了一种方法来打印它们。不幸的是,代码将无法编译,引用警告: “警告:[未检查] 未检查调用 add(E) 作为原始类型
尝试使用带有架构组件和Kotlin的Android Studio 3 Canary 5构建示例会给出此警告。 谁能告诉我原因? 谢谢,Ove 编辑#1: 这是Dan Lew前段时间制作的样本 http
我正在编写一个 Shiny 的应用程序,它运行得非常好,突然我收到两条警告消息。我已经回到以前运行良好的副本,它们现在显示相同的错误消息,所以我真的很困惑。我的代码仍然运行并在我 Shiny 的仪表板
03-25 05:52:15.329 8029-8042/com.mgh.radio W/MediaPlayerNative: info/warning (703, 0) 03-25 05:52:15
我在构建时在我的 gradle 控制台中收到一条警告消息: 警告:[options] 引导类路径未与 -source 1.7 一起设置 1 条警告 我怎样才能解决这个问题? 任何帮助表示赞赏! 最佳答
我有下一个代码: 测试.c #include "a1.h" int main() { int a = 8; foo(a); return a; } a1.h void foo
我的程序中有一个 WORD 变量。 WORD hour; 但是当我比较它的时候 if(hour>=0 && hour=0 && hour=0 的比较,它始终适用于 hour 是 WORD 类型,它是一
安全研究人员警告称,一个最新的严重的Java错误,其本质与目前在全球范围内利用的臭名昭著的 Log4Shell 漏洞相同 。 CVE-2021-42392 尚未在国家漏洞数据库 (NVD) 中
安装SqlServer2005时“版本变更检查 (警告)"问题排查 今天同事在安装SqlServer2005时遇到“版本变更检查 (警告) ”问题导致安装失败,警告提示如下: - 版本
我的 UWP 项目中出现以下警告。我已经标记了解决方案的示例,但我更感兴趣的是为什么在同一平台上创建另一个空项目时不会出现此警告? APPX4001: Build property AppxBundl
我试图修复我的登录脚本,在我的本地主机上它可以工作,但上传到我的在线测试服务器时,注销被破坏,我得到这个错误: Warning: session_destroy() [function.session
我是一名优秀的程序员,十分优秀!