SFML community forums

Help => General => Topic started by: Flash619 on November 02, 2012, 05:20:58 pm

Title: References returning null values?
Post by: Flash619 on November 02, 2012, 05:20:58 pm
Ok I'll admit, this is my mess up.  I even know whats wrong, I just don't know how to fix it. ^^;

So I have a little class *actually two classes* that I made to handle sprite/texture stuff to lower down the amount of re used code in other classes. What they do is very easy to figure out. If you want a sprite, you use get sprite, send it the path, it uses texture to retrieve the texture and such. But I'm trying to 1, figure out why its not working, and 2, trying to make a decision as to how to return the variables.

Option a, would be to use references *what I'm trying currently* but then that makes me wonder if it would conflict with other instances of the same class. *if two things tried to get a sprite at once*

Option b, Or if it would be better to just make a new copy of the variable every time. *would use more memory and such*.

As for the code here it is:
#include "stdafx.h"
#include "SpriteUtilities.h"
sf::Sprite& Sprite::getSprite(std::string path)
{
        Texture texture;
        sf::Sprite s;
        s.setTexture(texture.getTexture(path));

        return s;
}
sf::Texture& Texture::getTexture(std::string path)
{
        sf::Texture t;
        log.info("Attempting to load texture at: " + path);
        if(!t.loadFromFile(path))
        {
                log.error("Unable to load texture from path: " + path);
                log.error("Texture errors detected, graphic failure may occur!");
                return t;
        }
        return t;
}
 

The problem is that since the variable is declared in a outside class/function, the moment it returns the reference the memory allocation is cleared and it returns a blank sprite. I just don't really remember how to fix it. >.>'

So any help, and recommendations as to which way would be best to go, is greatly appreciated! :) I did indeed try pointers but they didn't just say error, they screamed it, all over my build log.  ::) So I decided to try references. ^^;;

Huge thanks in advance and as always, if you wish to know more just ask! :)
Title: Re: References returning null values?
Post by: FRex on November 02, 2012, 05:27:45 pm
You have to allocate it dynamically somewhere(do not attempt to use any new or delete in your code, that's what standard lib is for) preferably in std::map(textures) or just return a copy(sprites are ok to copy).
Title: Re: References returning null values?
Post by: Flash619 on November 02, 2012, 05:40:22 pm
I've never used std::map before. Would I just store the variable in there, and then transfer that?

Between the two options you mentioned which would you recommend? Either way I would like to learn more about dynamically allocating memory.
Title: Re: References returning null values?
Post by: FRex on November 02, 2012, 05:43:29 pm
This stores textures by paths(might contain errors, wrote it in like 30 seconds..):
class sss
{
private:
std::map<sf::Texture> mTextures;
public:
sf::Texture& get(const std::string& gName);
};

sf::Texture& sss::get(const std::string& gName)
{
std::map<sf::Texture>::iterator it = mTextures.find(gName);
if(it==mTexture.end())
{
mTextures[gName].loadFromFile(gName);
it = mTextures.find(gName);
}
return *it;
}
 
Sprites should be returned as copies and Textures as references or pointers. Methods depend on what you're returning. Containers from std:: allocate memory themselves, there is a few, deque, vector, map, list.
You can find full descriptions at cplusplus.com
Title: Re: References returning null values?
Post by: Flash619 on November 02, 2012, 05:46:59 pm
This stores textures by paths(might contain errors, wrote it in like 30 seconds..):
class sss
{
private:
std::map<sf::Texture> mTextures;
public:
sf::Texture& get(const std::string& gName);
};

sf::Texture& sss::get(const std::string& gName)
{
std::map<sf::Texture>::iterator it = mTextures.find(gName);
if(it==mTexture.end())
{
mTextures[gName].loadFromFile(gName);
it = mTextures.find(gName);
}
return *it;
}
 

Seems kinda similar to a Java hash map.  ;D
Title: Re: References returning null values?
Post by: FRex on November 02, 2012, 05:50:12 pm
This is not a hash map, this will be sorted, and if you use begin() and end() to iterate over that, it'll iterate in alphabetical order. Hash maps are(I think) under name unordered_map in boost, tr1 and c++11.
Title: Re: References returning null values?
Post by: Flash619 on November 02, 2012, 05:55:44 pm
This is not a hash map, this will be sorted, and if you use begin() and end() to iterate over that, it'll iterate in alphabetical order. Hash maps are(I think) under name unordered_map in boost, tr1 and c++11.

Yea that makes sense. I think I would just stick with the std::map tho and learn how to properly use that instead of going with a unordered map.

So would I have to have two maps then like?:

std::map<sf::Texture> mTextures; //Holds the textures.
std::map<sf::Sprite> mSprites; //Holds the sprites that get the textures from the texture map.
 

It seems like the easiest way but I'm not sure if there is a better one.

Also in your code at:

if(it==mTexture.end()) //Why did you check to see if the iterator was at the end of the map? Was that to check
{                                  //to see if there was already a instance of it in the map?
mTextures[gName].loadFromFile(gName);
it = mTextures.find(gName);
}
 
Title: Re: References returning null values?
Post by: FRex on November 02, 2012, 05:58:35 pm
Actually, map<sf::Texture> should be map<std::string,sf::Texture> instead. And 'return it->second;' instead of *it.
http://www.cplusplus.com/reference/stl/map/find/
There is no use in holding sprites in a map. Just return them as copy. That's what tutorials say.
Title: Re: References returning null values?
Post by: Flash619 on November 02, 2012, 06:07:31 pm
Actually, map<sf::Texture> should be map<std::string,sf::Texture> instead. And 'return it->second;' instead of *it.
http://www.cplusplus.com/reference/stl/map/find/
There is no use in holding sprites in a map. Just return them as copy. That's what tutorials say.

The only thing I still find confusing is the if statement. ^^;;; I solved the rest.

I just cant figure out what the "end()" is for.


OOOOH I think I get it, its because you told it to search for it, so then if its at the end it didn't find anything and then you add it?
Title: Re: References returning null values?
Post by: FRex on November 02, 2012, 06:14:45 pm
find() return iterator to element with that key or iterator equal to iterator returned by end() if element doesn't exist.
Title: Re: References returning null values?
Post by: Flash619 on November 02, 2012, 06:22:14 pm
find() return iterator to element with that key or iterator equal to iterator returned by end() if element doesn't exist.

So I have it setup like.....

#include "stdafx.h"
#include "SpriteUtilities.h"
sf::Sprite Sprite::getSprite(std::string path)
{
        Texture texture;
        sf::Sprite s;
        s.setTexture(texture.getTexture(path));

        return s;
}
sf::Texture& Texture::getTexture(std::string& path)
{
        std::map<std::string,sf::Texture>::iterator it = mTextures.find(path);
        if(it==mTextures.end())
        {
                log.info("Attempting to load texture at: " + path);
                if(!mTextures[path].loadFromFile(path))
                {
                        log.error("Unable to load texture from path: " + path);
                        log.error("Texture errors detected, graphic failure may occur!");
                        return it->second;
                }
                it = mTextures.find(path);
                return it->second;
        }

}
 

But When I do

                sf::Sprite GenesisLogo_S;
                GenesisLogo_S = sprite.getSprite("Resource/SplashScreen/PredawnStudios/Genesis_Logo_XL.png");
 

and I print it to the screen, its the right size, but it is still white.  :-\

Is it because of how I'm returning?
Title: Re: References returning null values?
Post by: FRex on November 02, 2012, 06:45:08 pm
sf::Sprite Sprite::getSprite(std::string path)
{
    Texture texture;
    sf::Sprite s;
    s.setTexture(texture.getTexture(path));

    return s;//HERE!!!
}
HERE!!! - Your texture object gets out of scope = it destroys all texture objects it allocated.
Title: Re: References returning null values?
Post by: Flash619 on November 02, 2012, 06:46:33 pm
sf::Sprite Sprite::getSprite(std::string path)
{
    Texture texture;
    sf::Sprite s;
    s.setTexture(texture.getTexture(path));

    return s;
}//HERE!!!
HERE!!! - Your texture object gets out of scope = it destroys all texture objects it allocated.

Well that's what I knew the problem was originally, but how do I return it to another class/file without it going out of scope?  ??? I mean, not using a "=" seems nearly impossible, but then again, I don't know everything about everything.

I figured that when you said to make a new copy of the sprite... that that's what you meant.
Title: Re: References returning null values?
Post by: FRex on November 02, 2012, 06:50:48 pm
I don't understand the question, it's too simple. c++ is all about RAII, pointers and classes, how can you miss that is.. ???
Honestly, what do Java developers do if none of the problems you had so far appear in Java? :o
Title: Re: References returning null values?
Post by: Flash619 on November 02, 2012, 06:54:19 pm
I don't understand the question, it's too simple. c++ is all about RAII, pointers and classes, how can you miss that is.. ???
Honestly, what do Java developers do if none of the problems you had so far appear in Java? :o

>.> I've only touched Java in my spare time to make modifications/plugins for Minecraft. ^^;;

What I'm saying is I don't understand how to make "return s;" not make variables go out of scope when it leaves the class. I understand the concept of "out of scope", and that its removing the memory allocation the moment I use "=" but I don't know how to do it any other way than that. As I said earlier, I tried it with pointers, it threw more errors than the references did.

And yes, I even understand why they throw an error. They throw a memory access violation. Meaning that its pointing to data that is "out of scope" and no longer there.

I do understand the concepts, but I don't actually know any of the hands on how to fix it stuff and because of that, a simple class like this, could quite literally, take me an entire day. That's why I come here for help hoping someone knows what it is I'm looking to do and can explain how. xD I know how to break things in code but how to fix things or rather "make things work" can be a mystery.

This code right here:

sf::Sprite GenesisLogo_S;
                GenesisLogo_S.setTexture(texture.getTexture("Resource/SplashScreen/PredawnStudios/Genesis_Logo_XL.png"));
 

Works just fine, so that kinda makes me realize that the "getSprite" function seems completely useless and a waste of code. After all either way I need to declare the sprite in my splash screen file, so if I use get sprite then what happens, it makes another sprite, so I have a sprite and another sprite, which seems wasteful to me and like it would *very very minutely* slow it down some.
Title: Re: References returning null values?
Post by: FRex on November 02, 2012, 07:07:49 pm
Shared pointers maybe. But there are simpler ways to deal with that. Manager classes put in well thought locations. See : http://en.sfml-dev.org/forums/index.php?topic=9437.msg64068#msg64068
Quote
the "getSprite" function seems completely useless and a waste of code
Yes!
Title: Re: References returning null values?
Post by: Flash619 on November 02, 2012, 07:46:16 pm
Shared pointers maybe. But there are simpler ways to deal with that. Manager classes put in well thought locations. See : http://en.sfml-dev.org/forums/index.php?topic=9437.msg64068#msg64068
Quote
the "getSprite" function seems completely useless and a waste of code
Yes!

Thanks for the link! It does seem a good idea to just include it in the main game state manager class, then I can just use that to sort of bounce off of to access it. Once I get a few new functions wrote for my window, I may try to take a look at that. :)
Title: Re: References returning null values?
Post by: Flash619 on November 02, 2012, 07:56:44 pm

Hey I was just wondering, whats your input on this?

int* EngineWindow::GetCenter()
{
        int *WindowCenter = new int[1]; //[0=X,1=Y]

        sf::Vector2u FullSize;

        FullSize = this->getSize();

        WindowCenter[0] = FullSize.x/2;
        WindowCenter[1] = FullSize.y/2;

        return WindowCenter;
}
 

I remember you saying not to use *new* but it does work with it, I just don't have a clue about how to delete it. It does work without error though. It returns a int Array.
Title: Re: References returning null values?
Post by: FRex on November 02, 2012, 08:09:42 pm
Does it really? Should cause access violation or stack corruption. It's also (possibly) leaking memory. Why can't you just return sf::Vector? There is no reason not to return sf::Vector or if you really need array : std::vector(which is unleaky, self resizing array).
Title: Re: References returning null values?
Post by: Flash619 on November 02, 2012, 08:15:52 pm
Does it really? Should cause access violation or stack corruption. It's also (possibly) leaking memory. Why can't you just return sf::Vector? There is no reason not to return sf::Vector or if you really need array : std::vector(which is unleaky, self resizing array).

Yep it somehow works. XD

I'll just use a sf::vector. Should I just return a copy then since its returning data to an outside class and get rid of the pointers?
Title: Re: References returning null values?
Post by: FRex on November 02, 2012, 08:17:40 pm
Yes! All functions that TAKE vector in SFML take const references or references and all functions that return vectors return a copy.
Title: Re: References returning null values?
Post by: Flash619 on November 02, 2012, 08:22:08 pm
TAKE vector in SFML take const references or references

???

Not sure what you are talking about there...

This is the code I came up with.... am I right?
sf::Vector2u& EngineWindow::GetCenter()
{
        sf::Vector2u WindowCenter;

        sf::Vector2u FullSize;

        FullSize = this->getSize();

        WindowCenter.x = FullSize.x/2;
        WindowCenter.y = FullSize.y/2;

        return WindowCenter;
}
 
Title: Re: References returning null values?
Post by: FRex on November 02, 2012, 08:27:48 pm
Functions are declared like this:
void doShitWithVector(const sf::Vector2f& vector);
sf::Vector2f calculateShitVector();
not like this:
void doShitWithVector(sf::Vector2f vector);//waste of memory passingvector by value
sf::Vector2f& calculateShitVector();//cant return reference to temporary vector from inside fucntion scope
Title: Re: References returning null values?
Post by: Flash619 on November 02, 2012, 08:29:20 pm
Functions are declared like this:
void doShitWithVector(const sf::Vector2f& vector);
sf::Vector2f calculateShitVector();
not like this:
void doShitWithVector(sf::Vector2f vector);//waste of memory passingvector by value
sf::Vector2f& calculateShitVector();//cant return reference to temporary vector from inside fucntion scope

But I'm not accepting any vectors in my functions. In fact.... I'm not accepting any input to them. They only create and return a vector.......
Title: Re: References returning null values?
Post by: FRex on November 02, 2012, 08:31:02 pm
Yes. So you return a copy. References are for things that are heavy to copy or for input values to functions.
Title: Re: References returning null values?
Post by: Flash619 on November 02, 2012, 08:36:22 pm
Yes. So you return a copy. References are for things that are heavy to copy or for input values to functions.

Oh that makes sense. I just often have difficulty figuring out whats considered a heavy copy. I suppose that would be things like.... sound objects, textures, stuff like that.
Title: Re: References returning null values?
Post by: FRex on November 02, 2012, 08:42:58 pm
Textures, Images, SoundBuffers are Heavy. Sprites, Sounds, Vectors are Light.(this list is not complete..)
Everything is written in SFML documentation usually.