有时在编程时,我们会定义或声明函数、定义、变量、宏包含和数据结构,但在此之后就不再使用它们了。1.那些未使用的资源是否会被编译器自动删除(现代编译器能够优化)?1.有没有办法辨认出那些东西?
d6kp6zgx1#
这取决于:宏被编译器转换成程序文本。它们只表示替换它们的文本,并且不会在编译时间之后存在(除非......见下文)。如果局部变量等没有非平凡的构造函数或析构函数,它们很可能会被删除。(您不希望仅仅因为在代码后面没有引用scoped_lock之类的内容就将其删除。)对于具有内部链接的变量和函数也是如此(例如,在命名空间作用域用关键字static定义)。然而,在大多数情况下,这种对象所需的资源是最小的,并且节省可以忽略。函数有点不同,而且依赖。如果有一个虚函数的类型的示例,那么它通常会被认为是“使用过的”,而且几乎肯定会出现,即使它从未被调用过。除此之外(这也适用于全局变量):这取决于链接器。大多数链接器的粒度是编译“翻译单元”产生的目标文件:该目标文件要么是要么不是你程序的一部分。如果你告诉链接器合并目标文件,那么你应该得到它里面的所有东西。如果你把目标文件放在一个(静态)库中,并告诉链接器使用它,那么当且仅当它解析了一个未解析的外部变量时,链接器才会将目标文件合并到你的程序中。但是如果它合并了目标文件,它通常会合并所有这些函数。(任何好的库都会将每个非虚函数放在单独的对象文件中,因此您不会得到超出需要的函数。)在这方面,DLL的行为就像目标文件(不管它们的名字)。如果你把你的目标文件链接到一个DLL中,使用它的程序将得到所有的DLL,或者一个也得不到。最后:虽然不是程序的一部分,但是目标文件和最终的可执行文件通常包含符号信息;最好的系统甚至会维护有关宏的信息,以便调试器可以按照您编写的方式显示内容。2(对于宏,它能做到什么程度是有争议的)。
scoped_lock
static
ep6jt1vc2#
如果编译器或链接器可以看到没有对C函数或C变量的引用,它们就可以(而且通常会)删除那些未使用的内容。未使用的宏定义根本不会进入编译代码,typedefs等也是如此。然而,删除程序的汇编部分中实现的未使用的代码和数据则比较困难。如果某个引用的变量或某个代码将要被使用或执行,编译器并不总是很清楚。所以,是的,这些天,大多数明显不用的东西都被拿走了。
2条答案
按热度按时间d6kp6zgx1#
这取决于:
宏被编译器转换成程序文本。它们只表示替换它们的文本,并且不会在编译时间之后存在(除非......见下文)。
如果局部变量等没有非平凡的构造函数或析构函数,它们很可能会被删除。(您不希望仅仅因为在代码后面没有引用
scoped_lock
之类的内容就将其删除。)对于具有内部链接的变量和函数也是如此(例如,在命名空间作用域用关键字static
定义)。然而,在大多数情况下,这种对象所需的资源是最小的,并且节省可以忽略。函数有点不同,而且依赖。如果有一个虚函数的类型的示例,那么它通常会被认为是“使用过的”,而且几乎肯定会出现,即使它从未被调用过。
除此之外(这也适用于全局变量):这取决于链接器。大多数链接器的粒度是编译“翻译单元”产生的目标文件:该目标文件要么是要么不是你程序的一部分。如果你告诉链接器合并目标文件,那么你应该得到它里面的所有东西。如果你把目标文件放在一个(静态)库中,并告诉链接器使用它,那么当且仅当它解析了一个未解析的外部变量时,链接器才会将目标文件合并到你的程序中。但是如果它合并了目标文件,它通常会合并所有这些函数。(任何好的库都会将每个非虚函数放在单独的对象文件中,因此您不会得到超出需要的函数。)
在这方面,DLL的行为就像目标文件(不管它们的名字)。如果你把你的目标文件链接到一个DLL中,使用它的程序将得到所有的DLL,或者一个也得不到。
最后:虽然不是程序的一部分,但是目标文件和最终的可执行文件通常包含符号信息;最好的系统甚至会维护有关宏的信息,以便调试器可以按照您编写的方式显示内容。2(对于宏,它能做到什么程度是有争议的)。
ep6jt1vc2#
如果编译器或链接器可以看到没有对C函数或C变量的引用,它们就可以(而且通常会)删除那些未使用的内容。
未使用的宏定义根本不会进入编译代码,typedefs等也是如此。
然而,删除程序的汇编部分中实现的未使用的代码和数据则比较困难。
如果某个引用的变量或某个代码将要被使用或执行,编译器并不总是很清楚。
所以,是的,这些天,大多数明显不用的东西都被拿走了。