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

Author Topic: Problem with constructors - game development  (Read 10660 times)

0 Members and 1 Guest are viewing this topic.

Hengad

  • Newbie
  • *
  • Posts: 19
    • View Profile
Re: Problem with constructors - game development
« Reply #15 on: September 06, 2015, 03:41:44 pm »
I wonder who are this "some people" you are talking about.

Nevermind I did research and many people say it's better to use smart pointers. The guy who said it shouldn't be used was some streamer in twitch who was making cool looking game, so I believed it.

Reference should be initialized in constructor:
class MyClass {
    OtherClass& m_oc;
    MyClass(OtherClass& oc) : m_oc(oc) {}
};

I think I get it, I still got some errors, but I am going to try it with some very simple code.

Quote from: Hengad
I've heard that even experienced programmers sometimes have problems with pointers.
[...]
PS. Many experienced programmers have said that it's better to write bad but working code, instead of writing nothing
[...]
Some people say that smart pointers shouldn't be used at all
Do you have concrete sources for those claims? What makes you consider those people experienced?

1. This guy was streamer too, he have programmed for 8 years, and he said that he sometimes gets in trouble with pointers, but will eventually still fix the problems.

2. I've read article where this was said, and few streamers (I watch a lot programming live streams) have said to me I should just do something, if I do nothing I won't learn anything, and when you write bad code and you run in trouble you will learn from that what you should not do and what you should.

3. I thought so, but now when you asked about it and I did research, it seems to be false.

No; I don't have anything concrete, this is just what I have heard from different places.

Quote from: GraphicsWhale
Pass a reference or pointer.

I am having trouble with it, but I'm going to try this with something simpler and then try to implement it to my game code.

shadowmouse

  • Sr. Member
  • ****
  • Posts: 302
    • View Profile
Re: Problem with constructors - game development
« Reply #16 on: September 06, 2015, 03:43:01 pm »
Smart pointers only manage memory and ownership. Raw pointers are still used for passive indirections, pointer arithmetic, and so on.
Just remembered this link which I think is really useful for the topic of should people be using raw pointers. http://www.lb-stuff.com/pointers

GraphicsWhale

  • Full Member
  • ***
  • Posts: 131
    • View Profile
Re: Problem with constructors - game development
« Reply #17 on: September 06, 2015, 04:04:02 pm »
This guy was streamer too, he have programmed for 8 years, and he said that he sometimes gets in trouble with pointers, but will eventually still fix the problems.

Programming in a nutshell.

I thought so, but now when you asked about it and I did research, it seems to be false.

While I do agree with using smart pointers, I do recommend you research what exactly they do before using them. Using them wrong can be just as stupid as not using them.

For example:
- Pass raw pointers to functions that do not assume ownership or operate on smart pointers
- Use unique_ptr instead of shared_ptr when possible
- Pass-by-reference is always better than pass-by-pointer

That's definitely not all, but should be enough to make my point about doing research first clear.

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Re: Problem with constructors - game development
« Reply #18 on: September 06, 2015, 04:20:07 pm »
@shadowmouse: Thanks for the article. The author makes some interesting observations, but he's also badly informed in several cases.
  • std::optional<T&> is indeed an interesting alternative to T*, as it documents the nullability better. But it is mainly useful for optional parameters, and I'm not sure if it will gain enough acceptance because of its syntax.
  • std::reference_wrapper<T> exists mainly for std::ref() and std::cref(). Using it instead of T* for passive indirections (weak references) is not the intention, which can already be seen by the fact that the class doesn't provide dereferencing operators. References cannot replace pointers because they're not rebindable and need immediate initialization.
  • Even in modern C++, many APIs still use a (T* begin, std::size_t length) signature to access contiguous ranges. Providing std::vector::iterator exposes implementation details for no reason. Saying that iterators would replace pointers entirely is thus wrong.
  • While function pointers lose some meaning in the presence of std::function, they're still used when initializing std::function. When used directly, they may achieve better performance than std::function.
  • Interfacing with low-level libraries is a point the author is missing entirely.
Of course, the conclusion "raw pointers will be completely useless" is silly regardless of the above-mentioned issues, as all of the alternatives in the article are implemented using pointers. That also applies to developers who implement smart pointers, containers and other wrappers themselves.
« Last Edit: September 06, 2015, 04:28:26 pm by Nexus »
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

shadowmouse

  • Sr. Member
  • ****
  • Posts: 302
    • View Profile
Re: Problem with constructors - game development
« Reply #19 on: September 06, 2015, 06:40:38 pm »
I agree with basically all of your points Nexus (I use reference_wrapper for polymorphic containers rather than pointers and am looking forward to optional, as I hate the need to dereference), but I think the article is very useful especially for people who think that smart pointers are evil and manual memory management is necessary.

Jesper Juhl

  • Hero Member
  • *****
  • Posts: 1405
    • View Profile
    • Email
Re: Problem with constructors - game development
« Reply #20 on: September 06, 2015, 07:12:45 pm »
I wonder who are this "some people" you are talking about.

Nevermind I did research and many people say it's better to use smart pointers. The guy who said it shouldn't be used was some streamer in twitch who was making cool looking game, so I believed it.

Some real C++ experts you should listen to instead:
 Bjarne Stroustrup
 Herb Sutter
 Scott Meyers
 Stephan T. Lavavej
 Andrei Alexandrescu

I can also recommend checking out the following list of links for great learning material and more:
 https://isocpp.org/
 https://isocpp.org/faq
 http://en.cppreference.com/w/
 https://channel9.msdn.com/Series/C9-Lectures-Stephan-T-Lavavej-Core-C-
 http://www.redblobgames.com/
 http://gameprogrammingpatterns.com/
« Last Edit: September 06, 2015, 07:14:58 pm by Jesper Juhl »

dabbertorres

  • Hero Member
  • *****
  • Posts: 506
    • View Profile
    • website/blog
Re: Problem with constructors - game development
« Reply #21 on: September 06, 2015, 08:03:41 pm »
I completely recommend Herb Sutter out of Jesper's list (all of them are great!). I watched one of his talks, and I found him entertaining and interesting to listen to, which can be difficult to do sometimes in the computer world! So he may be a good start if you find one of the others difficult/boring to listen to (I haven't listened to talks by all in Jesper's list, I'm just adding my experience!).

Hengad

  • Newbie
  • *
  • Posts: 19
    • View Profile
Re: Problem with constructors - game development
« Reply #22 on: September 06, 2015, 09:00:46 pm »
I can also recommend checking out the following list of links for great learning material and more:
 http://www.redblobgames.com/
 http://gameprogrammingpatterns.com/

I am having problem with this "very simple" passing object by reference thing, and you link some game developing book and algorithm stuff ;_; I tried to search for that object pass by reference thing but I didn't find anything useful and I couldn't get it work by my own.

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Re: Problem with constructors - game development
« Reply #23 on: September 06, 2015, 09:07:30 pm »
Jesper obviously didn't post those links in order to solve your current problem, but as general resources to learn... I don't think pass-by-reference is the last problem you'll ever encounter.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

shadowmouse

  • Sr. Member
  • ****
  • Posts: 302
    • View Profile
Re: Problem with constructors - game development
« Reply #24 on: September 06, 2015, 09:09:34 pm »
When you pass by value (default), the function effectively declares an object in local scope that is exactly the same as the one you passed, but it is a clone. When you pass by reference, the function has access to the actual object that was passed, no clone is constructed. The syntax is:
function declaration/definition
type function(paramType& paramName)
and you use it exactly as you would a normal function, no dereferencing, no address/reference operator.

Jesper Juhl

  • Hero Member
  • *****
  • Posts: 1405
    • View Profile
    • Email
Re: Problem with constructors - game development
« Reply #25 on: September 06, 2015, 09:12:01 pm »
Here's an object, constructed with some data:

std::vector<int> vi = {1, 1, 2, 3, 5, 8};

Here's a function taking that object by (const) reference and printing all its members:

void f(const std::vector<int>& obj)
{
    for (const auto& elem : obj) {
        std::cout << elem << std::endl;
    }
}

Clear enough?

Hengad

  • Newbie
  • *
  • Posts: 19
    • View Profile
Re: Problem with constructors - game development
« Reply #26 on: September 06, 2015, 09:25:56 pm »
Quote from: Nexus
Jesper obviously didn't post those links in order to solve your current problem, but as general resources to learn... I don't think pass-by-reference is the last problem you'll ever encounter.

You are right, but I mean that if this is "very simple" thing and yet hard for me, there is no sense I should go learn from those sources.

Quote from: Jesper Juhl
Here's an object, constructed with some data:

std::vector<int> vi = {1, 1, 2, 3, 5, 8};

Here's a function taking that object by (const) reference and printing all its members:

void f(const std::vector<int>& obj)
{
    for (const auto& elem : obj) {
        std::cout << elem << std::endl;
    }
}
 

Well yes I know how to do it with functions. I don't know how many times I've already said this; I just want to access Vector2f screenDimensions that is in WindowManager class, from both Core and World class, but I want constructor to be called only once. :)

Quote from: Jesper Juhl
Clear enough?

I have not learned c++11, but I understand what you are doing there.

shadowmouse

  • Sr. Member
  • ****
  • Posts: 302
    • View Profile
Re: Problem with constructors - game development
« Reply #27 on: September 06, 2015, 09:27:44 pm »
We know you want the constructor to be called only once. Create the WindowManager outside of Core or World and pass it to both by reference.

GraphicsWhale

  • Full Member
  • ***
  • Posts: 131
    • View Profile
Re: Problem with constructors - game development
« Reply #28 on: September 07, 2015, 02:24:46 am »
Just change your WindowManager instance in World to make it a reference:

class World
{
    public:
        World(WindowManager& windowManager);
        void createWorld();
        std::vector<sf::RectangleShape> vecGrassTile;
        std::vector<sf::RectangleShape> vecDirtTile;
    private:
        WindowManager& windowManager; //Now a reference
        int tileFullSize;
        sf::Vector2f tileSize;
        sf::RectangleShape grassTile;
        sf::RectangleShape dirtTile;
};

 

windowManager cannot be uninitialized, initializer lists let your initialize things before they get default-initialized:

World::World()
: windowManager(windowManager) //This is the initializer list
{
    std::cout << "World constructor" << std::endl;
    //here i initialize tile stuff, no problem, i cutted it out.
}
 

You will have to change the Core constructor:

Core::Core()
: firstMap(windowManager) //This ensures the windowManager is passed as a parameter to firstMap's constructor
{
    std::cout << "Core constructor" << std::endl;
    firstMap.createWorld();
    windowManager.createWindow();
}
 

Also:

- Initializer lists are basically how you call the constructor for member variables. Since ALL members must be assigned something before the constructor is called, but it's default-initialized. If you need to pass a
parameter, reference, int, pointer, even the class itself, you have to use an initializer list.

- Always place the order of which members in the initializer list appear to the order of which they were declared (if you have more than one you need to initialize).

- This counts for anything, really, but C++ isn't Java, don't pass an object to another object (via reference or pointer) without being 100% sure the object holding the reference/pointer will die before the object the reference/pointer is referring/pointing to. If you create A, then B with a reference to A, then destroy A before B, you create undefined behavior (technically, if it's a pointer and B stops using A as soon as A dies, it's not undefined behavior, but that's a pretty specific scenario). If you don't know which will die first, A or B, then that's where shared pointers come in (A would have to be declared as a shared pointer instead of a scoped variable, though). Fortunately, as long as you declare member variables in the order of which they depend on each other, this isn't a problem since they both die alongside each other when the "host" object dies.
« Last Edit: September 07, 2015, 02:43:59 am by GraphicsWhale »

Hengad

  • Newbie
  • *
  • Posts: 19
    • View Profile
Re: Problem with constructors - game development
« Reply #29 on: September 07, 2015, 03:12:41 pm »
After total of almost 30 posts I get the answer I have been waiting for. :)

Only this one thing:


World::World()
: windowManager(windowManager) //This is the initializer list
{
    std::cout << "World constructor" << std::endl;
    //here i initialize tile stuff, no problem, i cut it out.
}
 

It gave me error, but I fixed it by inserting parameter WindowManager& windowManager to constructor.
Now it compiles and doesn't call the constructor twice, thank you.
So it looks like this:

World::World(WindowManager& windowManager)
: windowManager(windowManager)
 

Is that correct way? Or is there something I should do differently?