基类指针:在哪里使用 new 和 delete
Base class pointer: where to use new and delete
我想知道我应该在以下类结构中在哪里使用new
和delete
:
#include <iostream>
class StateBase {
public:
StateBase( int val ) : m_stateInfo(val) {}
virtual ~StateBase() {}
virtual int getState() = 0;
protected:
int m_stateInfo;
};
class StateImpl1 : public StateBase {
public:
StateImpl1() : StateBase( 1 ) {}
~StateImpl1() {}
int getState() {
//std::cout << "stateimpl:" << m_stateInfo << std::endl;
return m_stateInfo;
}
};
class DeviceBase {
public:
DeviceBase( StateBase* pState ) : mp_state( pState ) {}
~DeviceBase() {} // TODO or delete here? but then it's a bit asymmetric...
virtual void work() = 0;
protected:
StateBase* mp_state;
};
class DeviceImpl1 : public DeviceBase {
public:
DeviceImpl1() : DeviceBase( new StateImpl1() ) {}
// TODO d'tor here? but then base is left without valid ptr to "mp_state"
~DeviceImpl1() { delete mp_state; }
void work() {
std::cout << "DeviceImpl1 work: state = " << mp_state->getState() << std::endl;
}
};
int main() {
DeviceImpl1 impl1;
impl1.work();
return 0;
}
我猜,将delete
放在基类中是不对称的,而且可读性较差。 在派生类(调用new
(中使用 delete
会使基类具有无效指针(如果只是很快,但它不干净(。
- 在派生类中使用它,将 PTR 设置为
NULL
并检查基类中NULL
的指针可能是一个选项 - 也许整个设计有缺陷? 如果是这样:还有什么替代方案?
更新: 我不能使用现代C++因为它必须使用交叉编译器
使用 unique_ptr
管理所有权/生存期/内存:
#include <iostream>
#include <memory>
#include <utility>
class StateBase {
public:
StateBase( int val ) : m_stateInfo(val) {}
virtual ~StateBase() {}
virtual int getState() = 0;
protected:
int m_stateInfo;
};
class StateImpl1 : public StateBase {
public:
StateImpl1() : StateBase( 1 ) {}
~StateImpl1() {}
int getState() {
return m_stateInfo;
}
};
class DeviceBase {
public:
DeviceBase( std::unique_ptr<StateBase> ) : mp_state( std::move(pState) ) {}
virtual ~DeviceBase() {}
virtual void work() = 0;
protected:
std::unique_ptr<StateBase> mp_state;
};
class DeviceImpl1 : DeviceBase {
public:
DeviceImpl1() : DeviceBase( std::make_unique<StateImpl1>() ) {}
~DeviceImpl1() = default;
void work() {
std::cout << "DeviceImpl1 work: state = " << mp_state->getState() << std::endl;
}
};
int main() {
DeviceImpl1 impl1;
impl1.work();
return 0;
}
在现代C++中,您将 1. 找出所需的所有权语义,然后 2. 使用适当的内存管理工具(如智能指针(表达它们。值得注意的是,您从不手动执行内存管理。这种努力应该封装在一个唯一负责内存管理的类中(请参阅单一责任原则(。
#include <iostream>
#include <memory>
class StateBase {
public:
StateBase( int val ) : m_stateInfo(val) {}
virtual ~StateBase() {}
virtual int getState() = 0;
protected:
int m_stateInfo;
};
class StateImpl1 : public StateBase {
public:
StateImpl1() : StateBase( 1 ) {}
~StateImpl1() {}
int getState() {
//std::cout << "stateimpl:" << m_stateInfo << std::endl;
return m_stateInfo;
}
};
class DeviceBase {
public:
// Constructor says: Give me exclusive ownership of a StateBase.
DeviceBase(std::unique_ptr<StateBase> pState) : mp_state(std::move(pState)) {}
// Destructor (implicitly generated) takes care of cleanup.
virtual void work() = 0;
protected:
std::unique_ptr<StateBase> mp_state;
};
class DeviceImpl1 : DeviceBase {
public:
DeviceImpl1() : DeviceBase(std::make_unique<StateImpl1>()) {}
// Base class constructor handles cleanup.
void work() {
std::cout << "DeviceImpl1 work: state = " << mp_state->getState() << std::endl;
}
};
int main() {
DeviceImpl1 impl1;
impl1.work();
return 0;
}
我们在这里所做的只是澄清DeviceBase
拥有StateBase
的独特所有权。通过这样做,我们可以消除所有析构函数(std::unique_ptr
为我们处理内存管理,另请参阅 RAII(。我更喜欢= default;
而不是空的析构函数实现,但这在很大程度上无关紧要。自动生成的 DeviceBase
析构函数将调用unique_ptr
析构函数,该析构函数将delete
存储的StateBase
实例。
请注意,您的原始代码不遵循三/五/零的规则,因此在尝试复制类的实例时会遇到问题(阅读:双释放等(。在上面使用 std::unique_ptr
的代码中,无法复制 DeviceBase
和 DeviceImpl1
类(因为无法复制std::unique_ptr
成员(。
继承公共基类:
#include <iostream>
class StateBase {
public:
StateBase(int val) : m_stateInfo(val) {}
virtual ~StateBase() {}
virtual int getState() = 0;
protected:
int m_stateInfo;
};
class StateImpl1 : public StateBase {
public:
StateImpl1() : StateBase(1) {}
~StateImpl1() {}
int getState() {
//std::cout << "stateimpl:" << m_stateInfo << std::endl;
return m_stateInfo;
}
};
class DeviceBase {
public:
DeviceBase(StateBase* pState) : mp_state(pState) {}
~DeviceBase() {} // TODO or delete here? but then it's a bit asymmetric...
virtual void work() = 0;
protected:
StateBase* mp_state;
};
class DeviceImpl1 : **public DeviceBase** { // Change is here
public:
DeviceImpl1() : DeviceBase(new StateImpl1()) {}
// TODO d'tor here? but then base is left without valid ptr to "mp_state"
~DeviceImpl1() { delete mp_state; }
void work() {
std::cout << "DeviceImpl1 work: state = " << mp_state->getState() << std::endl;
}
};
如何初始化 DeviceImpl1 实例 impl1 并调用 delete 来执行这两个析构函数:
int main() {
DeviceImpl1* impl1 = new DeviceImpl1();
DeviceBase* base = impl1;
impl1->work();
delete base; // This will execute both of the destructor.
return 0;
}
相关文章:
- new[] / delete[] 并在C++中抛出构造函数/析构函数
- QQuickView new-delete-type-mismatch
- 创建 myNew/myDelete 以替换 new/new[]/delete/delete[]
- 为多线程环境包装 c++ new/delete 的安全/好方法
- c++ 运算符 new[]/delete [] 是否调用运算符 new/delete?
- C++内存分配失败(使用 new & delete)
- c++重载运算符new delete
- 在 C++ 中将 malloc/free 替换为 new/delete
- new/delete 和 ::new/::d elete 有什么区别?
- 我什么时候应该在C++中重载new/delete
- 在C++中,"new/delete"在结构上代替"malloc/free"有多好?
- 为什么我的信号槽比QThreadPool+new+delete慢
- malloc()/free()/new/delete/delete[] 的算法复杂度是多少?
- C++中new[]/delete[]与new/delete之间的差异
- 标准C++的哪些部分将调用malloc/free而不是new/delete
- C++中的 malloc/free 和 new/delete 兼容性
- 编译器将 malloc/free 或 new/delete 对优化为 alloca
- 在 ANSI C 中使用 new/delete 的缺点
- 为什么使用 malloc/free,当我们有 new/delete 时
- c++如何知道在new/delete之后指向内存的位置