Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: References returning null values?  (Read 9675 times)

0 Members and 3 Guests are viewing this topic.

Flash619

  • Full Member
  • ***
  • Posts: 142
    • View Profile
References returning null values?
« 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! :)

FRex

  • Hero Member
  • *****
  • Posts: 1848
  • Back to C++ gamedev with SFML in May 2023
    • View Profile
    • Email
Re: References returning null values?
« Reply #1 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).
Back to C++ gamedev with SFML in May 2023

Flash619

  • Full Member
  • ***
  • Posts: 142
    • View Profile
Re: References returning null values?
« Reply #2 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.
« Last Edit: November 02, 2012, 05:42:24 pm by Flash619 »

FRex

  • Hero Member
  • *****
  • Posts: 1848
  • Back to C++ gamedev with SFML in May 2023
    • View Profile
    • Email
Re: References returning null values?
« Reply #3 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
« Last Edit: November 02, 2012, 05:48:11 pm by FRex »
Back to C++ gamedev with SFML in May 2023

Flash619

  • Full Member
  • ***
  • Posts: 142
    • View Profile
Re: References returning null values?
« Reply #4 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

FRex

  • Hero Member
  • *****
  • Posts: 1848
  • Back to C++ gamedev with SFML in May 2023
    • View Profile
    • Email
Re: References returning null values?
« Reply #5 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.
Back to C++ gamedev with SFML in May 2023

Flash619

  • Full Member
  • ***
  • Posts: 142
    • View Profile
Re: References returning null values?
« Reply #6 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);
}
 

FRex

  • Hero Member
  • *****
  • Posts: 1848
  • Back to C++ gamedev with SFML in May 2023
    • View Profile
    • Email
Re: References returning null values?
« Reply #7 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.
Back to C++ gamedev with SFML in May 2023

Flash619

  • Full Member
  • ***
  • Posts: 142
    • View Profile
Re: References returning null values?
« Reply #8 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?
« Last Edit: November 02, 2012, 06:15:00 pm by Flash619 »

FRex

  • Hero Member
  • *****
  • Posts: 1848
  • Back to C++ gamedev with SFML in May 2023
    • View Profile
    • Email
Re: References returning null values?
« Reply #9 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.
Back to C++ gamedev with SFML in May 2023

Flash619

  • Full Member
  • ***
  • Posts: 142
    • View Profile
Re: References returning null values?
« Reply #10 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?

FRex

  • Hero Member
  • *****
  • Posts: 1848
  • Back to C++ gamedev with SFML in May 2023
    • View Profile
    • Email
Re: References returning null values?
« Reply #11 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.
« Last Edit: November 02, 2012, 06:46:56 pm by FRex »
Back to C++ gamedev with SFML in May 2023

Flash619

  • Full Member
  • ***
  • Posts: 142
    • View Profile
Re: References returning null values?
« Reply #12 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.
« Last Edit: November 02, 2012, 06:51:29 pm by Flash619 »

FRex

  • Hero Member
  • *****
  • Posts: 1848
  • Back to C++ gamedev with SFML in May 2023
    • View Profile
    • Email
Re: References returning null values?
« Reply #13 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
Back to C++ gamedev with SFML in May 2023

Flash619

  • Full Member
  • ***
  • Posts: 142
    • View Profile
Re: References returning null values?
« Reply #14 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.
« Last Edit: November 02, 2012, 07:06:09 pm by Flash619 »