如果方法在类中定义,则阻止编译器删除方法
Prevent compiler from removing methods if methods are defined inside class
免责声明:
我对以下风格是否是"良好做法"的意见不感兴趣。我正在寻找解决问题的答案/方法。
问题:
我正在 cpp 文件中编译一个类。编译过程剥离了我的方法定义,它认为这些定义是"未使用的"。有什么办法可以防止这种情况吗? (请参阅下面的开发环境示例(
开发环境:
我现在正在使用g++ --std=c++98
。一个完美的解决方案将在所有 c++98 标准编译器和更新版本上提供。
例:
例1.cpp
#include <stdio.h>
class Example1{
public:
void print(){printf("helloWorld");};
};
编译、汇编和链接该文件不会创建print()
方法。(g++ --std=c++98 example1.cpp main.cpp
,其中main.cpp
简单地调用打印方法。
编译这个(没有链接,g++ --std=c++98 -S
(将输出:
例1.s
.file "example1.cpp"
.text
.ident "GCC: (Ubuntu 9.2.1-9ubuntu2) 9.2.1 20191008"
.section .note.GNU-stack,"",@progbits
.section .note.gnu.property,"a"
.align 8
.long 1f - 0f
.long 4f - 1f
.long 5
0:
.string "GNU"
1:
.align 8
.long 0xc0000002
.long 3f - 2f
2:
.long 0x3
3:
.align 8
4:
这里显然没有生成print()
方法。
不好的解决方法
如果我在同一文件中使用它,我可以让编译器生成该方法(请参阅下面的代码(。但是,我正在寻找更好的解决方案。也许编译器选项?
例1.cpp
#include <stdio.h>
class Example1{
public:
void print(){printf("helloWorld");};
};
// Create a function outside the class, that uses print().
// That way, print will be generated.
void foo(){
Example1 ex;
ex.print();
}
备注(编辑(:
- 在类之外定义方法是不可能的。
Example1
在main.cpp
中的用法如下:
主.cpp
class Example1{
public:
void print();
};
int main(){
Example1 example;
example.print();
return 0;
}
简短的回答是"你不能使用标准C++"。
较长的答案分为几个部分。
首先,您的解决方法没有实现您认为的效果。
#include <stdio.h> class Example1{ public: void print(){printf("helloWorld");}; }; // Create a function outside the class, that uses print(). // That way, print will be generated. void foo(){ Example1 ex; ex.print(); }
这不会阻止编译器Example1::print()
"删除"成员函数。 没有什么可以阻止编译器在foo()
内联Example1::print()
调用,并且(使用您的措辞(以(例如(可以通过链接器解析的形式生成该函数。
二、你的"主.cpp">
如果class Example1{ public: void print(); }; int main(){ Example1 example; example.print(); return 0; }
与"example1.cpp"的任一版本在同一项目中使用它,则会引入未定义的行为,因为类Example1
的定义明显不同 - 一个在类定义中定义成员函数print()
,另一个则不然。 这打破了单定义规则,因为您的程序有两个不同的类Example1
定义。
如果你的第二个"example1.cpp"似乎"有效"(无论你如何评估(,那么你就是很幸运。 未定义行为的本质意味着它似乎可以工作。 问题是,C++标准没有给出任何这样的保证 - 当行为未定义时,编译器被允许做它喜欢的事情 - 你的代码似乎可以"工作",或者它可能做一些完全不同的事情。
通常解决此类问题的方式是将类Example1
的定义放在单独的头文件中,例如
// example1.h
#include <stdio.h>
class Example1{
public:
void print(){printf("helloWorld");};
};
然后将该标头包含在需要它的所有源文件中。 例如;
// example1.cpp
#include "example1.h"
void foo()
{
Example1 ex;
ex.print();
}
和
// main.cpp
#include "example1.h"
int main()
{
Example1 example;
example.print();
return 0;
}
然后,上述两个源文件(示例 1.cpp 和 main.cpp(可以在同一程序中安全地使用。
由于函数Example1::print()
是内联定义的,因此编译器可以自由地内联它。 编译器仍然不需要内联,但允许这样做。 这意味着,生成的对象文件或可执行文件不一定包含任何可识别的(例如通过检查程序集(作为函数Example1::print()
。 在您的示例中,可能只有main()
和foo()
中的代码调用printf()
,但没有明显名为Example1::print()
的函数。
正如另一个答案(您拒绝了,随后被删除(所说,防止内联的唯一方法是在类定义之外定义函数。 该函数定义需要恰好位于项目中的一个编译单元中。 这允许编译器"生成"函数,但在技术上不需要它(允许智能编译器和链接器"删除"该函数(。
根据彼得的评论Microsoft具体
从这里
您可以创建对无法优化的调试函数的错误引用。为此,请将指向调试函数的指针传递给模块外部的帮助程序函数,该函数不执行任何有趣的操作。由于帮助程序函数不在模块中,因此编译器不知道帮助程序函数不执行任何操作,因此无法优化调试函数。
struct ForceFunctionToBeLinked {
ForceFunctionToBeLinked(const void *p) { SetLastError(PtrToInt(p)); }
};
ForceFunctionToBeLinked forceTestMe(TestMe);
- 检测win32服务创建和删除的最佳方法
- 尝试了解在导入的静态方法上使用删除方法时的错误
- 一种从内存中删除 UTF 字节的方法?
- 从数组中删除非唯一值、保持顺序和不使用向量的最佳方法?
- 在析构函数中删除单链表的正确方法是什么?
- 处理从列表中删除指向对象的指针的"healthy"方法是什么?
- 删除类成员的动态分配内存的最佳方法是什么
- 从浮点数中删除小数部分但保留类型的有效方法
- 如果方法在类中定义,则阻止编译器删除方法
- 删除复制构造函数的 Intel 13.1.2 中不良C++行为的解决方法
- 有没有一种预处理器的方法可以从调试符号中删除代码段
- 删除父/子窗口层次结构的最佳方法
- 工厂方法创建的对象应该在哪里删除?
- 如何通过最快的方法删除指定的标签组件
- 无法使用擦除方法删除矢量的最后一个元素
- 尝试使用窗口注册表中的路径和 DeleteFile() 方法删除.exe文件
- 通过此方法删除链表中的数据会发生什么情况
- 如何使用c++使用流的方法删除文件
- 如何通过析构函数方法删除对象(类)
- 标准的c++11方法删除一个类型的所有指针