1

What is the standard practice of creating a map and returning it to a function as a reference?

In my example, I am just creating a hashmap of the character count from a string, and doing this twice. I see that to return it from the function, the map would have to be created dynamically, otherwise, it would go out of scope and lead to undefined behavior.

However, I don't know how to add to the map, with just a pointer to it. (see code map[*it] += 1;), and I'm not sure if I'm going about the process in the correct way.

#include <iostream>
#include <map>


std::map<char, int>& createMap(std::string& myString){
    std::map<char, int>* map = new std::map<char, int>();
    for(std::string::iterator it = myString.begin(); it != myString.end(); ++it){
        map[*it] += 1;
    }
    return map;
}

void turnStringsIntoMaps(std::string a, std::string b){
    std::map<char, int> firstMap = createMap(a);
    std::map<char, int> secondMap = createMap(b);
    for(auto it = m.begin(); it != m.end(); ++it){
        std::cout << it->first << " : " << it->second << '\n';
        std::cout << m[it->first] << '\n';
    }
    return true;
}
Dan Savage
  • 25
  • 3

2 Answers2

2

What is the standard practice of creating a map and returning it to a function as a reference?

There is no "standard practice" of what you want to do, because, frankly, it is unusual.

When you want a function to return a map then make it return a map:

std::map<char, int> createMap(std::string& myString){
    std::map<char, int> myMap;
    // ...
    return myMap;
}

Returning a reference to a local variable is usually a problem:

int& foo() { int x; return x; }

because the reference returned is dangling (the x is long gone when the caller gets the reference). For more on that read here.

It seems you tried to workaround that problem by using dynamic memory allocation. However, this is not necessary. Rather it is to be avoided! Standard containers already manage their memory and most of the time allocating a container on the heap is a code smell.

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
0

Without knowing more about why you'd like to do this, you have a couple of options.

#include <map>
#include <iostream>
#include <string>

std::map<char, int> CreateMap(const std::string& myString){
    std::map<char, int> new_map;
    for(const auto& it : myString){
        new_map[it] += 1;
    }
    return new_map; // copy elision means no performance loss
}

int main()
{
    auto my_map = CreateMap(std::string("testing"));
    
    for (const auto& iter: my_map){
        cout << iter.first << "  " << iter.second << endl;
    }

    return 0;
}

The compiler automatically skips copying the return value of a function by constructing the returned local variable in the same place as the variable on the call-side.

Another option might be to create the map on the call side, and pass it in by ref:

void CreateMap(const std::string& my_string, std::map<char, int>& my_map);

Usage:

std::map<char, int> my_map;
CreateMap("teststring", my_map);
SwappyG
  • 88
  • 7