为什么编译器在声明对象std :: vector但从未使用时不发出警告?

Jov*_*ini 16 c++ compiler-warnings unused-variables

#include <vector>

class Object
{
};

int main()
{
    Object myObject;
    std::vector<int> myVector;
}
Run Code Online (Sandbox Code Playgroud)

编译器发出:

warning: unused variable 'myObject' [-Wunused-variable]
Run Code Online (Sandbox Code Playgroud)

没有警告myVector.为什么?有没有办法实现这个?

Jon*_*fer 21

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

在第一种情况下,构造函数是微不足道的(甚至没有声明),对于析构函数是相同的.由于Object没有成员,它很清楚,很容易检测到,Object foo实际上没有任何东西.

std::vector有一个非平凡的构造函数,可以分配内存(外部状态+函数,其定义可能不知道(new ...))与非平凡的析构函数(也是外部状态+函数,其定义可能不知道(delete ...)).在这种情况下,不可能推断出是否可以安全地删除声明(因此发出警告暗示你可能应该这样做),因此编译器必须将声明留在代码中(并且必须假设声明是为了原因).

一个主要的例子是std::lock_guard用于在构造互斥锁时锁定它,并在它被破坏时自动解锁.只要对象在范围内,就可以保持互斥锁; 通常你根本不会访问该std::lock_guard对象 - 但是声明它是有用的.这是RAII的工作原则.

在这种情况下发出警告将是一种麻烦,导致人们关闭警告,这反过来会使警告无效.(编译器甚至可以设计为只有在优化过程中删除了声明时才会发出警告,这也是为什么只有在启用某些优化时才显示某些警告的原因.)


mar*_*inj 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
}
Run Code Online (Sandbox Code Playgroud)

[编辑]

来自gcc属性页面:https://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html:

warn_unused对于具有非平凡构造函数和/或析构函数的C++类型,编译器无法确定此类型的变量在未被引用时是否真正未使用.此类型属性通知编译器,如果它们看起来未被使用,则应警告此类型的变量,就像基本类型的变量一样.此属性适用于仅表示值的类型,例如std :: string; 它不适合控制资源的类型,例如std :: lock_guard.

C中也接受此属性,但这是不必要的,因为C没有构造函数或析构函数.

  • @MarcGlisse你是对的(我的意思是标记了99%的libstdc ++),这里有关于此的公开讨论:https://gcc.gnu.org/bugzilla/show_bug.cgi?id = 55203. (2认同)