关于在构造函数中将临时绑定到引用成员的虚假警告
Spurious warning about binding temporary to reference member in constructor
我知道,如果临时绑定到构造函数初始值设定项列表中的引用成员,则该对象将在构造函数返回时被销毁。
但是,请考虑以下代码:
#include <functional>
#include <iostream>
using callback_func = std::function<int(void)>;
int
func(const callback_func& callback)
{
struct wrapper
{
const callback_func& w_cb;
wrapper(const callback_func& cb) : w_cb {cb} { }
int call() { return this->w_cb() + this->w_cb(); }
};
wrapper wrp {callback};
return wrp.call();
}
int
main()
{
std::cout << func([](){ return 21; }) << std::endl;
return 0;
}
这对我来说是完全有效的。callback
对象将在func
函数的整个执行过程中存在,并且不应该为wrapper
的构造函数创建临时副本。
事实上,GCC 4.9.0在启用所有警告的情况下编译良好。
但是,GCC 4.8.2编译器会向我发出以下警告:
$ g++ -std=c++11 -W main.cpp
main.cpp: In constructor ‘func(const callback_func&)::wrapper::wrapper(const callback_func&)’:
main.cpp:12:48: warning: a temporary bound to ‘func(const callback_func&)::wrapper::w_cb’ only persists until the constructor exits [-Wextra]
wrapper(const callback_func& cb) : w_cb {cb} { }
^
这是误报还是我误解了对象的寿命
以下是我测试的确切编译器版本:
$ g++ --version
g++ (GCC) 4.8.2
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ g++ --version
g++ (GCC) 4.9.0 20140604 (prerelease)
Copyright (C) 2014 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
这是gcc 4.8中的一个错误,已在4.9中修复。这是错误报告:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=50025
正如Howard Hinnant所指出的,R Sahu的评论已经指出的,这是GCC 4.8处理初始值设定项列表的方式中的一个错误(这曾经是当时被破坏的标准所要求的;感谢Tony D指出了这一点)。
从更改我原来示例中的构造函数
wrapper(const callback_func& cb) : w_cb {cb} { }
至
wrapper(const callback_func& cb) : w_cb (cb) { }
使GCC 4.8.3的警告消失,并清除创建的可执行文件Valgrind。这两个程序集文件的差异很大,所以我不在这里发布它。GCC 4.9.0为两个版本创建相同的程序集代码。
接下来,我用一个用户定义的结构替换了std::function
,并删除了复制和移动构造函数和赋值运算符。事实上,在GCC 4.8.3中,这保留了警告,但现在也给出了一个(稍微有用一点)错误,即上面的代码行调用了结构的已删除副本构造函数。正如预期的那样,与GCC 4.9.0没有区别。
相关文章:
- 非静态成员引用必须相对于特定对象
- 在C++中,如果成员引用在其声明中初始化,为什么需要存储空间?
- 成员引用基类型 'char' 不是 C++ 中的结构或联合
- 成员引用基类型不是结构或联合
- for 循环说 - 错误 成员引用基类型"int [13]"不是结构或联合
- 成员引用基类型 'double [10]' 不是结构或联合
- 使用默认值初始化成员引用
- 错误:成员引用基类型"uint32_t"(也称为"无符号 INT")不是结构或联合
- 无法用2D矢量成员引用对象
- 是否可以在同一对象中对成员 std::shared_ptr 进行成员引用<variable>?
- 是否有一种方法可以将C 类成员引用到向量而不明确添加它们
- C++:成员引用还是指针
- C++非静态成员引用
- C++ 成员引用基类型'int'不是结构或联合
- 将成员引用变量置于成员指针变量之上的原因
- C++非静态成员引用必须相对于特定对象
- 无法理解错误 msg:"非静态成员引用必须相对于特定对象"
- 返回类成员引用变量会导致运行时错误
- 可以安全地将移动的对象存储在成员引用中
- 成员引用基类型'double'不是结构或联合