#include <vector>
class Object
{
};
int main()
{
Object myObject;
std::vector<int> myVector;
}
编译器发出:
warning: unused variable 'myObject' [-Wunused-variable]
没有警告myVector
。为什么?有什么办法可以启用它吗?
#include <vector>
class Object
{
};
int main()
{
Object myObject;
std::vector<int> myVector;
}
编译器发出:
warning: unused variable 'myObject' [-Wunused-variable]
没有警告myVector
。为什么?有什么办法可以启用它吗?
声明(并因此初始化并在某些时候破坏)任意对象是否具有可见的副作用通常无法确定。构造函数可能正在调用编译器不知道其定义的函数,或者它可能取决于外部状态或任何其他使问题无法确定的方面。
在您的第一种情况下,构造函数是微不足道的(甚至没有声明),对于析构函数也是如此。由于Object
没有成员,因此Object foo
实际上什么都不做很清楚且易于检测。
std::vector
有一个非平凡的构造函数,它可能正在分配内存(外部状态+其定义可能未知的函数(new ...
))和一个非平凡的析构函数(也是外部状态+其定义可能未知的函数(delete ...
))。在这种情况下,无法推断删除声明是否安全(从而发出警告提示您可能应该这样做),因此编译器必须将声明留在代码中(并且必须假设声明存在一段时间)原因)。
一个典型的例子是std::lock_guard
,它用于在构造互斥体时锁定它,并在它被破坏时自动解锁它。因此,只要对象在范围内,互斥锁就会被持有;通常,您根本不会访问该std::lock_guard
对象——尽管声明它是有用的。这就是 RAII 原则在起作用。
在这种情况下发出警告会很麻烦,导致人们关闭警告,这反过来又会使警告变得无用。(编译器甚至可以设计为仅在优化期间删除声明时才发出警告,这也是某些警告仅在启用某些优化时才显示的原因。)
此警告仅针对普通类型生成。编译器无法确定构造是否会调用任何外部函数。如果您向Object
类中添加构造函数,那么编译器也会发出警告。Gcc 允许标记应生成此警告的类型,您可以使用以下方法执行此操作__attribute__((warn_unused))
:
http://coliru.stacked-crooked.com/a/0130c8ef29c121a1
例子:
class __attribute__((warn_unused)) Object
{
public:
Object(){}
void use() {}
};
int main()
{
Object myObject; // will give : warning: unused variable 'myObject' [-Wunused-variable]
//myObject.use(); // uncomment to hide this warning
}
[编辑]
来自 gcc 属性页面:https ://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html :
warn_unused对于具有非平凡构造函数和/或析构函数的 C++ 类型,编译器无法确定该类型的变量如果没有被引用,它是否真正未被使用。此类型属性通知编译器如果此类变量似乎未使用,则应警告它们,就像基本类型的变量一样。此属性适用于仅表示值的类型,例如 std::string;它不适用于控制资源的类型,例如 std::lock_guard。
这个属性在 C 中也被接受,但它是不必要的,因为 C 没有构造函数或析构函数。
除了上面的答案,还要检查你的编译器文档。可以设置一些编译器,使它们不会多次显示相同的警告。如果您注释掉“myObject”的声明,您可能会收到与“myVector”相同的警告。“mObject”首先产生该警告,您不会收到“myVector”的警告。
警告情况下的编译器行为是非常特定于编译器的,因此不要假设所有编译器都以相同的方式工作。:)