在没有 delete 运算符的情况下编译 C++
Compiling C++ without the delete operator
我正在为嵌入式设备编写 C++ 程序,我想在没有 libstdc++、异常和动态内存分配的情况下编译它。
示例程序:
#include <stdio.h>
class A
{
public:
virtual ~A() {}
virtual void Foo() = 0;
};
class B : public A
{
public:
virtual ~B() {}
virtual void Foo() override{}
};
int main()
{
B b;
return 0;
}
马上我运行进入如下错误。
$ gcc src.cpp -static -fno-rtti -fno-exceptions -std=c++11
/tmp/ccd0Wydq.o: In function A::~A()':
src.cpp:(.text._ZN1AD2Ev[_ZN1AD5Ev]+0x29): undefined reference to
operator delete(void*)' /tmp/ccd0Wydq.o: In function A::~A()':
src.cpp:(.text._ZN1AD0Ev[_ZN1AD5Ev]+0x20): undefined reference to
operator delete(void*)' /tmp/ccd0Wydq.o: In function B::~B()':
src.cpp:(.text._ZN1BD2Ev[_ZN1BD5Ev]+0x35): undefined reference to
operator delete(void*)' /tmp/ccd0Wydq.o: In function B::~B()':
src.cpp:(.text._ZN1BD0Ev[_ZN1BD5Ev]+0x20): undefined reference to
operator delete(void*)'
/tmp/ccd0Wydq.o:(.rodata._ZTV1A[_ZTV1A]+0x20): undefined reference to
`__cxa_pure_virtual' collect2: error: ld returned 1 exit status
Makefile:2: recipe for target 'all' failed make: *** [all] Error 1
我理解为什么需要 __cxa_pure_virtual
,但我终究无法理解为什么我需要 delete
实现。
我在代码中没有执行 new
或 delete
操作,为什么需要它?
当实现两个函数以满足链接器的要求时,似乎两者都没有被调用(正如预期的那样)。
有没有办法避免实现这些功能?
当通过 delete
表达式调用虚拟析构函数时,被调用的 operator delete
由最派生的 class 的范围确定。例如,
#include <iostream>
class Base {
public:
virtual ~Base() {}
};
void destroy_base(Base* b) { delete b; }
class Derived : public Base {
public:
static void operator delete(void* ptr) {
std::cout << "Derived::operator delete\n";
::operator delete(ptr);
}
};
int main() {
destroy_base( new Derived );
}
打印 "Derived::operator delete"
,即使函数 destroy_base
不知道 class Derived
.
g++ 通过在每个 class 的 vtable 中放置两个版本的析构函数来实现这一点:一个只销毁成员和基础,另一个完成所有这些然后调用适当的 operator delete
.这是您未定义符号的来源。
如果您从未真正使用过 delete
表达式,只需删除 ::operator delete
函数就可以了。
我正在为嵌入式设备编写 C++ 程序,我想在没有 libstdc++、异常和动态内存分配的情况下编译它。
示例程序:
#include <stdio.h>
class A
{
public:
virtual ~A() {}
virtual void Foo() = 0;
};
class B : public A
{
public:
virtual ~B() {}
virtual void Foo() override{}
};
int main()
{
B b;
return 0;
}
马上我运行进入如下错误。
$ gcc src.cpp -static -fno-rtti -fno-exceptions -std=c++11
/tmp/ccd0Wydq.o: In function
A::~A()': src.cpp:(.text._ZN1AD2Ev[_ZN1AD5Ev]+0x29): undefined reference to
operator delete(void*)' /tmp/ccd0Wydq.o: In functionA::~A()': src.cpp:(.text._ZN1AD0Ev[_ZN1AD5Ev]+0x20): undefined reference to
operator delete(void*)' /tmp/ccd0Wydq.o: In functionB::~B()': src.cpp:(.text._ZN1BD2Ev[_ZN1BD5Ev]+0x35): undefined reference to
operator delete(void*)' /tmp/ccd0Wydq.o: In functionB::~B()': src.cpp:(.text._ZN1BD0Ev[_ZN1BD5Ev]+0x20): undefined reference to
operator delete(void*)' /tmp/ccd0Wydq.o:(.rodata._ZTV1A[_ZTV1A]+0x20): undefined reference to `__cxa_pure_virtual' collect2: error: ld returned 1 exit status Makefile:2: recipe for target 'all' failed make: *** [all] Error 1
我理解为什么需要 __cxa_pure_virtual
,但我终究无法理解为什么我需要 delete
实现。
我在代码中没有执行 new
或 delete
操作,为什么需要它?
当实现两个函数以满足链接器的要求时,似乎两者都没有被调用(正如预期的那样)。
有没有办法避免实现这些功能?
当通过 delete
表达式调用虚拟析构函数时,被调用的 operator delete
由最派生的 class 的范围确定。例如,
#include <iostream>
class Base {
public:
virtual ~Base() {}
};
void destroy_base(Base* b) { delete b; }
class Derived : public Base {
public:
static void operator delete(void* ptr) {
std::cout << "Derived::operator delete\n";
::operator delete(ptr);
}
};
int main() {
destroy_base( new Derived );
}
打印 "Derived::operator delete"
,即使函数 destroy_base
不知道 class Derived
.
g++ 通过在每个 class 的 vtable 中放置两个版本的析构函数来实现这一点:一个只销毁成员和基础,另一个完成所有这些然后调用适当的 operator delete
.这是您未定义符号的来源。
如果您从未真正使用过 delete
表达式,只需删除 ::operator delete
函数就可以了。