我在C 上写了一个小游戏引擎,它可以正常工作,但不是最好的表演。我也学到了很多东西,我想现在重做。但是上次我大量使用共享的_ptr来用于GUI纹理和模型包装器(即3D位置和OpenGL VAO)等类。我已经听说不应该真正使用shared_ptr,但是我真的不知道该怎么做。这是类似伪代码的布局:
此代码不完整或有效,但我想分享我的布局
的想法// d3 stands for 3d
class D3Model {
VAO vao;
bool useBloom;
unsigned int texture;
// ... and so on
static std::vector<std::shared_ptr<D3Model>> models; // current idea, approach 1
static std::vector<D3Model> models1; // different approach (2)
D3Model() {
models.push_back(shared_from_this()); // app.1
models1.push_back(*this);
}
}
// main file
int main() {
std::shared_ptr<D3Model> model = std::make_shared<D3Model>();
model->setTexture(0); // ignore the non sense content
D3Model model1;
model1.setTexture(0); // would not get updated in the vector
while(true) {
model->increaseRotation(1);
model1.increaseRotation(1);
Renderer::render();
}
}
// different file
class Renderer {
static void render() {
for(const auto& all : D3Model::models) {
// render model
}
for(const auto& all : D3Model::models1) {
// render model1, would not have increased rotation
}
}
}
要进行更多澄清,请想象引擎的以下使用:在开始屏幕上播放播放后,引擎从文件中加载了一些3D型号并存储它们。其中一个旋转每个框架,每个框架都会渲染。由于游戏玩法的变化(玩家加入...),也许必须加载其他一些型号。然后,当用户返回主菜单时,它们都将被删除。我在方法2的问题是,每次增加模型的旋转时,我都必须更新矢量,而该方法会自动使用方法1进行处理。但是,我听到了共享_ptr对性能不利。
。对于这种情况,共享_ptr是最好的解决方案,还是我应该只使用普通对象?但是我的问题是,我将如何将更改应用于对象(例如setTexture),而无需更新矢量内容。原始的指针也非常好。这样的事情怎么办?谢谢,虚幻
好的,您可以像我这样创建自己的repcouner类:
/// RefCounter.hpp
#pragma once
class RefCounter {
public:
RefCounter();
RefCounter(const RefCounter&);
RefCounter& operator=(const RefCounter&);
void grab();
usize reference() const;
bool release();
protected:
virtual void finalize();
virtual ~RefCounter();
private:
usize _reference;
};
template<typename T>
struct ref {
inline ref() : class_ptr (nullptr) {}
inline ref(T* obj) : class_ptr (obj) { if(class_ptr) class_ptr->grab(); }
inline ref(const ref& other) : class_ptr (other.class_ptr) { if(class_ptr) class_ptr->grab(); }
inline ref& operator=(T* obj) {
if(obj)
obj->grab();
if(class_ptr)
class_ptr->release();
class_ptr = obj;
return *this;
}
inline ref& operator=(const ref& other){
T* obj = other.class_ptr;
if(obj)
obj->grab();
if(class_ptr)
class_ptr->release();
class_ptr = obj;
return *this;
}
T* get() const {
return class_ptr;
}
operator T*() const {
return class_ptr;
}
T* operator->() const {
return class_ptr;
}
inline ~ref() {
if(class_ptr)
class_ptr->release();
}
private:
T* class_ptr;
};
/// RefCounter.cpp
RefCounter::RefCounter() : _reference(0){
}
RefCounter::RefCounter(const RefCounter&) : _reference(0) {
}
RefCounter& RefCounter::operator=(const RefCounter&) {
return *this;
}
void RefCounter::grab() {
_reference++;
}
usize RefCounter::reference() const {
return _reference;
}
bool RefCounter::release() {
if(_reference > 1) {
_reference--;
return false;
} else {
_reference = 0;
finalize();
return true;
}
}
void RefCounter::finalize() {
delete this;
}
RefCounter::~RefCounter() {
}