0

I'm having trouble understanding why passing my array, containing elements, to a function, results in my array no longer containing elements within the function.

Before passing in an array containing 3 objects from my items sturct, the size of the array is 72 (24 for each object). Once inside the function, the size of my array is 24, which I assumed to be the size of the first element in my array. However, this is not the case.

My question, why isn't my array the same in the function as it is outside of the function?

Header File:

#include <iostream>
using namespace std;

// header file for shop items
struct items
{
    string name;
    int price;
    string examine;
};

main file:

#include "shop_items.h"
#include <iostream>

using namespace std;

int getLongestName(items &shop)
{   
    /*Iterates over each element in array
     if int longest < length of element's name, longest = length of element's name.*/

    int longest = 0;

    // shop size is 24, the size of a single element.
    cout << "sizeof(shop) right inside of function:" << sizeof(shop) << endl; 

    return longest;
}

void test1()
{   
    // initialize shop items
    items sword;
    items bow;
    items shield;

    // set the name, price, and examine variables for each item.
    sword.name = "sword";   sword.price = 200;  sword.examine = "A sharp blade.";
    bow.name = "bow";       bow.price = 50;     bow.examine = "A sturdy bow.";
    shield.name = "sheild"; shield.price = 100; shield.examine = "A hefty shield.";

    // create an array for iterating over the each element in item shop.
    items shop[] = {sword, bow, shield};

    //sizeOfShop = 72, 24 for each element (the sword, bow and shield).    
    cout << "sizeof(shop) right outside function: " <<  sizeof(shop) << endl; 


    int longest = getLongestName(*shop);

}

int main()
{
    test1();
    cout << "\n\nPress the enter key to exit." << endl;
    cin.get();
}

What is useful about a reference-to-array parameter?

The answer to the above question has helped me a lot at better understanding what it is that I'm trying to do. However, I'm running into different errors when attempting to pass my array by reference as well.

Community
  • 1
  • 1
John Hall
  • 11
  • 2
  • 2
    But you are not passing an array by reference. Or by value. You are passing a single element by reference. – juanchopanza Jul 17 '14 at 20:06
  • 1
    You are passing the first element of the array by reference, not the array by value. Anyway, neither C nor C++ allows you to pass an array by value. You can simulate it by using containers / `struct`s containing the array though. – Deduplicator Jul 17 '14 at 20:09
  • 1
    Did you mean to use something like [`int getLongestName(std::vector &shop)`](http://en.cppreference.com/w/cpp/container/vector)? – πάντα ῥεῖ Jul 17 '14 at 20:09
  • or [this](https://stackoverflow.com/questions/2559896/how-are-arrays-passed?rq=1) ... or [this](https://stackoverflow.com/questions/2559896/how-are-arrays-passed?rq=1) ... or [this](https://stackoverflow.com/questions/15277638/why-is-sizeof-c-array-of-structs-different-inside-a-function-it-is-passed-into?rq=1) ... – Deduplicator Jul 17 '14 at 20:13
  • @Deduplicator, Thanks for the reference to that other question. It's similar enough for me to understand what I've been doing wrong. – John Hall Jul 17 '14 at 20:17
  • Don't use raw arrays. Use std::vector. – Rob K Jul 17 '14 at 20:19
  • You are trying to use low level abstractions of C, you should do that only when you understand the language well enough and only when necessary. Otherwise use std::vector – Slava Jul 17 '14 at 20:20
  • @RobK: Good advice comes with a rationale, so you know when it applies. – Deduplicator Jul 17 '14 at 20:22
  • @πάνταῥεῖ no, as I'm staying away from std:vector as I study the uses and limitations of the default array. – John Hall Jul 17 '14 at 20:33
  • @JohnHall _'I study the uses and limitations of the default array. – John Hall 2 mins ago'_ OK, then I recommend studying it from an [`std::array`](http://en.cppreference.com/w/cpp/container/array) implementations viewpoint, if you really want to get it for c++, as your actual tagging suggests. – πάντα ῥεῖ Jul 17 '14 at 20:37
  • @πάνταῥεῖ Does that mean std:array is c++ implementation while the default arrays are c implementation? I've been under the assumption that the default array is just a basic c++ array. – John Hall Jul 17 '14 at 20:40
  • @JohnHall I'd say if the current c++ standard defines it, yes this is the _default_ to use for c++. c compatibility of actual c++ implementation stands still though. `std::array` was introduced to overcome all of these problems (like passing by reference issues, etc.) occurring with plain c-style arrays. – πάντα ῥεῖ Jul 17 '14 at 20:44
  • @πάνταῥεῖ Thanks. That's something I wasn't aware of. – John Hall Jul 17 '14 at 21:00

1 Answers1

1

You do not pass the array. You pass only the first element of the array.

int longest = getLongestName(*shop);

Expression *shop is equivalent to shop[0] So inside the function you get the size of one object of type items.

Moreover you declared function getLongestName as having parameter of type reference to an object of type items.

int getLongestName(items &shop);

If you wanted to pass the whole array by reference to the function then you should declare it as

int getLongestName( items ( &shop )[3] );

and the function has to be called as

int longest = getLongestName(shop);

Or as

int getLongestName(items *shop, size_t n);

where the second parameter specifies the number of elements in the array.

And the function has to be called as

int longest = getLongestName(shop, 3 );
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • I see... Then can you tell me how I would pass the entire array instead of the first element? By passing in shop I get an error. How must I change my function definition to accommodate? – John Hall Jul 17 '14 at 20:14
  • You could send the size as a second parameter, also, you could require that the last element be null and test for it. More info here: http://stackoverflow.com/questions/2188991/what-is-useful-about-a-reference-to-array-parameter?lq=1 and http://stackoverflow.com/questions/1641957/is-array-name-a-pointer-in-c – MatiasFG Jul 17 '14 at 20:15
  • @John Hall See my updated post. – Vlad from Moscow Jul 17 '14 at 20:17
  • 1
    @JohnHall The question you linked tells you exactly how to pass an array by reference. If you want to pass by value, you will need a different type, such as `std::array`. – juanchopanza Jul 17 '14 at 20:18
  • @VladfromMoscow Thanks, I'll be reviewing my code and doing more practice examples. I'm really working towards not specifying the array's size in the function's definition. I'm also staying away from std::array and std::vector for now. For me it's more about understanding arrays and their limitations. – John Hall Jul 17 '14 at 20:30
  • A technique you could use if you feel strongly about not passing the array size and not using std::vector is to add another element to your structure, `bool isLast`. Set this member to `false` in all elements of your array except the last one, where it will be `true`. That's one way to do it while avoiding the techniques you don't want. – Logicrat Jul 17 '14 at 20:41
  • @logicrat The problem with that is, if I were to add more items to the shop array, i would have to remember change the isLast variable to true for that last item. I could easily determine which element of my array has the longest name, in the scope of my function test1() that contains the array shop. The problem I ran into was getting my function (getLongestName()) to treat my array the same inside the function, as it was outside of function. – John Hall Jul 18 '14 at 18:08
  • @JohnHall I completely agree about the problem with tagging the last element. I would probably declare `shop` as `std::vector`. `std::vector` provides a `size()` method that will tell you how many elements it has, and that method can be used within any function that you pass it to, whether by pointer or by reference. – Logicrat Jul 18 '14 at 20:30