C++: Making method return the same object every time

∥☆過路亽.° 提交于 2019-12-24 04:59:38

问题


I would like to have a function that loads a file (in this case an OpenGL texture), but only actually loads the file once, and every time it is called after that it just returns what it initially loaded.

What would be a good way to do this?

Thanks.


回答1:


You need some place to store that state. That can be either inside an object or as a static variable. Let's say:

class TextureLoader {
public:
    TextureLoader() {}
    GLuint loadTexture(std::string const & filename){
        std::map<std::string, GLuint>::iterator it = m_loadedTextures.find(filename);
        if(it == m_loadedTextures.end()){
            GLuint id = load(filename);
            m_loadedTextures[filename] = id;
            return id;
        }
        else{
            return it->second;
        }
    }
    ~TextureLoader(){
        // iterate and delete textures
    }
private:
    GLuint load(std::string const & filename){
        // real loading
    }
    std::map<std::string, GLuint> m_loadedTextures;
};



回答2:


One way to do this would be to have a static map inside the function that associates the parameters to the function (here, the filename) with a pointer to the unique value it returns. You can then have the function check whether the map contains the input and, if so, hand back the texture associated with it. Otherwise, you can then do the load, store the result in the map, and hand back the result. For example:

Texture* LoadTexture(const std::string& filename) {
    static std::map<std::string, Texture*> previousResults;

    /* Look up existing value. */
    Texture* result = previousResults[filename];

    /* If this doesn't exist, then go create it and pretend it was there all along. */
    if (result == NULL)
        result = previousResults[filename] = ActuallyLoadTexture(filename);

    /* Hand back the cached result. */
    return result;
}

If you do this, you should be careful about thread-safety, since multiple calls to the function could cause problems with the map. Syncrhonize as appropriate.




回答3:


It sounds like what you are looking for is an implementation of the Singleton Design Pattern.

There are a variety of ways to implement this, and now that you know what it is called, you can decide what method is best. Your first stop could be a search of this site for other similar questions.




回答4:


Typically, you would either associate with a map or unordered_map filepaths to Texture*s.

class render_state {
    std::map<std::string, Texture> textures;
    Texture* load_texture(std::string filepath) {
        if (textures.find(filepath) != textures.end()) {
            return &textures[filepath];
        }
        // load the texture here if it's not in cache
    }
    // Other rendering methods and state here.
};

But now, you have another problem, which is that sometimes you might use a relative filepath, or sometimes, an absolute filepath. Also, in some libraries, they can accept varying versions of newlines and backslashes or forward slashes. What if I loaded a Texture, then only used it for a specific time and didn't need it again? Whoops, memory leak.

The best thing to do is just return a Texture object (or (possibly smart) pointer to such) and let the user worry about managing it. If someone creates a resource, it's their job to manage it, not yours.




回答5:


See boost::flyweight. It does pretty much what you want. Load objects avoiding duplicates.




回答6:


Would this be what you are looking for:

Texture& loadTexture(cosnt std::string& texture)
{
    // Store all loaded data here
    // Each file maps to a loded texture object
    static boost::ptr_map<std::string, Texture>   data;

    boost::ptr_map<std::string, Texture>::iterator find = data.find(texture);
    if (find == data.end())
    {
        // If it is not in the structure then load it this one time
        find = data.insert(texture, doLoad(texture));
    }

    // return a reference to the texture
    return *(find->second);
}


来源:https://stackoverflow.com/questions/4589543/c-making-method-return-the-same-object-every-time

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!