• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
noatom

How is this a pass by value?!

12 posts in this topic

// maximum of two C-strings (call-by-value) 
inline char const* max (char const* a, char const* b) 
{ 
    return std::strcmp(a,b) < 0 ? b : a; 
} 

// maximum of three values of any type (call-by-reference) 
template <typename T> 
inline T const& max (T const& a, T const& b, T const& c) 
{ 
    return max (max(a,b), c); // error, because max(a,b) uses call-by-value 
} 

int main () 
{ 
    

    const char* s1 = "frederic"; 
    const char* s2 = "anica"; 
    const char* s3 = "lucas"; 
    ::max(s1, s2, s3); // ERROR 

} 

So when the 3 parameter function is called, it takes a constant reference to the listed pointers. So basically inside the function, a would be a constant reference to a constant pointer.

 

Then the 2 parameter max function is called, which takes a constant char pointer(WHY IS IT THEN CONSIDERED BY VALUE, when clearly we see it takes pointers, and not values!)

 

Its kinda late here, maybe I'm interpreting this in a very stupid way, can someone clear it up for me?

Edited by noatom
0

Share this post


Link to post
Share on other sites

Your code generates no errors for me, only a warning about returning a reference to a local variable. What exactly is the purpose of this code and why have you written it this way with templates and references?

Edited by Chris_F
0

Share this post


Link to post
Share on other sites

The following works for me:

 

#include <iostream>
#include <algorithm>
#include <cstring>

template<class T>
constexpr const T& max(const T& a, const T& b, const T& c)
{
    return std::max(std::max(a, b), c);
}

inline const char* max(const char* a, const char* b)
{
    return std::strcmp(a,b) < 0 ? b : a;
}

int main ()
{
    const char* s1 = "frederic";
    const char* s2 = "anica";
    const char* s3 = "lucas";
    std::cout << max(s1, s2, s3);
}
0

Share this post


Link to post
Share on other sites

Its from a template book, more exactly: Adison Wesley's C++ Templates The Complete Guide.

 

In the chapter he's showing template functions and overloading, and he gave this example. He was trying to show how writing too many overloads can cause a headache and make mistakes in code, aka returning a reference to a local.

 

But the problem is, he says in the commented code that the two arg function is a call by value, which is not! I'll give you the full code.

// maximum of two values of any type (call-by-reference) 
template <typename T> 
inline T const& max (T const& a, T const& b) 
{ 
    return a < b ? b : a; 
} 

// maximum of two C-strings (call-by-value) 
inline char const* max (char const* a, char const* b) 
{ 
    return std::strcmp(a,b) < 0 ? b : a; 
} 

// maximum of three values of any type (call-by-reference) 
template <typename T> 
inline T const& max (T const& a, T const& b, T const& c) 
{ 
    return max (max(a,b), c); // error, if max(a,b) uses call-by-value 
} 

int main () 
{ 
    ::max(7, 42, 68); // OK 

    const char* s1 = "frederic"; 
    const char* s2 = "anica"; 
    const char* s3 = "lucas"; 
    ::max(s1, s2, s3); // ERROR 

} 

But I just noticed another thing: Why wouldn't the 3 parameter function call the first function, which takes its parameters by reference?! the 3 parameter function itself has its parameters by reference, so it would only make sense to call the first function, and not the second.

 

 

 

I know the code works, the problem is I can't get the: "error, if max(a,b) uses call-by-value" how would it be called by value when we can clearly see it takes pointers and not values?!

Edited by noatom
0

Share this post


Link to post
Share on other sites

I know the code works, the problem is I can't get the: "error, if max(a,b) uses call-by-value" how would it be called by value when we can clearly see it takes pointers and not values?!

You are confused about what is actually passed to the function. In your max-function that is overloaded for char const *, the pointers a and b are not references to the pointers you pass to it, but value-copied of the original pointers. If you are confused about pointers and pass-by-value, it is easier to hide the pointer behind a typedef.

typedef char const *cstring;

cstring max (cstring a, cstring b)
{ ... }

Now compare with passing int, or float, or double, or char, and you'll see that the cstring object, which is a char const *, is actually passed by value.

2

Share this post


Link to post
Share on other sites
In your max-function that is overloaded for char const *, the pointers a and b are not references to the pointers you pass to it

I never said they are references, I was trying to say that I'm basically passing a pointer to a function which requires pointers, so why would there be values involved at all?!

Wasn't pointer assignment supposed to only copy the address?

Edited by noatom
0

Share this post


Link to post
Share on other sites

The pointers are passed by value to the function, and returned by value from the function. That's the problem here; the pointer that is returned from the max function is then returned from a function that returns a reference to the pointer. Since the return value is local to the function, the reference is thus a reference to a local value.

 

As I said, replace your char const * types with my cstring typedef and see where the values and references to local values comes into the picture. Pointers are not treated differently that any other int, float or double value.

0

Share this post


Link to post
Share on other sites

But how do you pass a pointer by value, since a pointer's value is an address?! If a and b are pointers, and b points to something, doing a = b, doesn't create another object, is just makes a point to the very same object that b points to.

Edited by noatom
0

Share this post


Link to post
Share on other sites

Step away from your nested max functions a bit and examine this program.

void set(char const *value)
{
    value = "bar";
}

void set(int value)
{
    value = 42;
}

int main ()
{
    int ivalue = 0;
    char const *svalue = "foo";

    set(ivalue);
    set(svalue);

    std::cout << ivalue << " " << svalue << std::endl;
}

Now answer these two questions, and understand why the answer is what it is.

  1. Is the value of ivalue 0 or 42?
  2. Does the pointer svalue point to the string "foo" or "bar"?

This is what is the core of the problem with your max functions.

Edited by Brother Bob
1

Share this post


Link to post
Share on other sites


But how do you pass a pointer by value, since a pointer's value is an address?
Copy the value of that address. The value of the pointer (an address as you said) is stored somewhere, when you call that function, its value gets copied and handed over to the function. The function uses that value to see where the pointer pointed to. Passing the pointer by its value.
0

Share this post


Link to post
Share on other sites

Ivalue will obviously remain 0 since we pass by value, and svalue will become bar(because we use a pointer).

 

That was my initial response without running the code. To my surprise, after running it, i was right about ivalue, but not about svalue.

 

Looking at the code again, I realized that foo is actually a literal, hence, it cannot be changed at all. Is that why the pointers are copied by value? Is there some kind of rule about 2 pointers refering to the same literal?

Edited by noatom
0

Share this post


Link to post
Share on other sites

Ivalue will obviously remain 0 since we pass by value, and svalue will become bar(because we use a pointer).

 

That was my initial response without running the code. To my surprise, after running it, i was right about ivalue, but not about svalue.

 

Looking at the code again, I realized that foo is actually a literal, hence, it cannot be changed at all. Is that why the pointers are copied by value? Is there some kind of rule about 2 pointers refering to the same literal?

svalue is a pointer variable, and a copy of its value is passed to the set function. The set function then assigns the local variable a new value, but the original pointer remains the same.

 

Now replace the two set functions with these instead that takes the parameters by reference.

void set(char const *&value)
{
    value = "bar";
}

void set(int &value)
{
    value = 42;
}

As I said, pointers are variables that work just like any other type. They just happen to have additional functionality that lets you access other objects through the pointer, but the pointers themselves are just values that are copied like any other value.

 

edit: There is a huge difference between a pointer, and the object a pointer points to. The pointer is copied, but the pointed-to object is not and can be reassigned across functions.

Edited by Brother Bob
1

Share this post


Link to post
Share on other sites

Triple-facepalm-picard-812.jpg

 

 

I can't believe I didn't notice this:

 

I failed so hard because I was thinking about objects. You know, you have an object, and 2 pointers, a pointer points to it, and you make the second pointer point to it too, and no matter which pointer changes something about the object(using the dereference op, which is not used here, another triple facepalm for me), the other pointer will obviously see the change too.

 

Here, the situation was more like: the 2 pointers point to the same object, but later one of them is made to point to another different object...

void set(char const *&value)

There you took a reference to a pointer, and of course doing any change inside the function is actually made to the pointer outside the function.

 

 

 

You could've in a way, modify the outside char array if you could use the dereference operator, but since the array is constant(because its a literal), there is no way in which you can change the array.(ONLY if you were to dynamicly allocate it, you could freely change the array) and of course, not take a pointer to a constant value as an argument.

 

I explained it so if anyone will ever have the same problem as me, will see things the clear way.(MASSIVE HINT: Look for the GODDAMN dereference operator damn it!)

 

I'm literally cringing in shame when I think about this....oh god....

 

Thanks Brother Bob smile.png

Edited by noatom
1

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0