19
#include <vector>

class Object
{
};

int main()
{
    Object myObject;
    std::vector<int> myVector;
}

编译器发出:

warning: unused variable 'myObject' [-Wunused-variable]

没有警告myVector。为什么?有什么办法可以启用它吗?

4

3 回答 3

24

声明(并因此初始化并在某些时候破坏)任意对象是否具有可见的副作用通常无法确定。构造函数可能正在调用编译器不知道其定义的函数,或者它可能取决于外部状态或任何其他使问题无法确定的方面。

在您的第一种情况下,构造函数是微不足道的(甚至没有声明),对于析构函数也是如此。由于Object没有成员,因此Object foo实际上什么都不做很清楚且易于检测。

std::vector有一个非平凡的构造函数,它可能正在分配内存(外部状态+其定义可能未知的函数(new ...))和一个非平凡的析构函数(也是外部状态+其定义可能未知的函数(delete ...))。在这种情况下,无法推断删除声明是否安全(从而发出警告提示您可能应该这样做),因此编译器必须将声明留在代码中(并且必须假设声明存在一段时间)原因)。

一个典型的例子是std::lock_guard,它用于在构造互斥体时锁定它,并在它被破坏时自动解锁它。因此,只要对象在范围内,互斥锁就会被持有;通常,您根本不会访问该std::lock_guard对象——尽管声明它是有用的。这就是 RAII 原则在起作用。

在这种情况下发出警告会很麻烦,导致人们关闭警告,这反过来又会使警告变得无用。(编译器甚至可以设计为仅在优化期间删除声明时才发出警告,这也是某些警告仅在启用某些优化时才显示的原因。)

于 2016-06-20T08:53:21.173 回答
6

此警告仅针对普通类型生成。编译器无法确定构造是否会调用任何外部函数。如果您向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 没有构造函数或析构函数。

于 2016-06-20T09:05:34.100 回答
2

除了上面的答案,还要检查你的编译器文档。可以设置一些编译器,使它们不会多次显示相同的警告。如果您注释掉“myObject”的声明,您可能会收到与“myVector”相同的警告。“mObject”首先产生该警告,您不会收到“myVector”的警告。

警告情况下的编译器行为是非常特定于编译器的,因此不要假设所有编译器都以相同的方式工作。:)

于 2016-06-20T09:59:49.683 回答