Assume we have the following case:
If it is morning mood is good otherwise mood is bad
Print the mood
it could be written as:
std::string mode; //this cost us calling the constructor of std::string
if(time==Morning){ // a real code should be here
mood="Good"//re assign the string
}
else{
mood="bad"//re assign the string
}
std::cout << mood;
assuming it is not std::string, it is a very big object. Isn't it too luxury to declare "mode" and call the constructor for no reason!
Is using the raw pointer a solution? what is the best practice here?
thanks
You could use the ternary operator to initialize the string.
std::string mode = (time == Morning ? "Good" : "Bad")
As MSalters pointed out in the comments this is actually still two constructions(constructor + copy) but it should get optimized by the compiler. You can directly initialize the string with
std::string mode { (time == Morning ? "Good" : "Bad") };
I would consider putting the logic into a separate function. This helps to keep functions small and simple.
std::string moodAtTime(Time time)
{
if(time==Morning)
{ // a real code should be here
return "Good";
}
else
{
return "bad";
}
}
std::string mood = moodAtTime(t);
This reduces function length and splits the code into small units performing simple questions.
If it is only for initialization, you can use a lambda to do it without the named function:
std::string mood = [](Time t)
{
if(t==Morning)
{
return "Good";
}
else
{
return "bad";
}
}(now);
The cost gets high if you enter that specific scope allot of times, and yes, it could get very expensive (depending on the what's happening inside the scope) .
The solution would be to keep either a global variable, or more widely used, a pool of such objects (object pools / memory are widely used for such purposes, especially in the case of small and very small objects).
So, to explain in code
// scope that is entered allot, like 100k times per second
{
std::string temp;
...
// magic happens
...
}
Quick solution
{
static std::string g_uniqueNamed_temp_string;
...
// magic happens
...
}
Elegant solution
EDIT : switched to raw pointers to avoid copying
{
std::string* tempString = StringPool::GetAPreallocatedString();
...
// magic happens
...
}
You can use alloca for that:
#include <iostream>
#include <sstream>
using namespace std::literals;
int main() {
void *mem = alloca(sizeof(std::string)); //Allocates memory on stack; no initialization
std::string *mood;
if(true){ // a real code should be here
mood = new (mem) std::string("Good");//re assign the string
}
else{
mood=new (mem) std::string("Bad");//re assign the string
}
std::cout << *mood;
return 0;
}
Related
The one annoyance I have with the std::string class is that the only ways (that I could figure out after reading cplusplus.com's info about it) to get the location of the last character in the string is (stringVariable.length() - 1) or stringVariable.rfind(stringVariable.back()). It'd be nice if I could just do stringVariable.last(). This is for a function I wrote in a personal project that needs to reference this number of a user's input string.
Some ideas I had were creating a struct that is just a string and has the last() function as a member function, or a class that copies the string class and adds that member. With a struct, I'm not sure how (or if it's possible) to make it so I can make the variable assigned to the type automatically reference the string in it so that I don't need to make a constant member call. I'm taking the second C++ class in school right now, but we haven't touched on C++ classes yet.
I tried reading some guides and answers here about classes, and they don't look all that different from structs, but the more complex stuff in either case was Greek to me. I only learned how to use a struct as a holder for multiple variable types; like the name string and id int for a person, or something like that. I learned from the guides I can put functions in them, and define operator behavior too, but when I tried to define operator behavior for the string struct I made, I couldn't get it to work.
Based on the example I read, I tried:
str &operator=(const str &ing)
{
s = ing.s;
return s;
}
But when I tried to test it by using = to copy a str variable to a string variable I could cout, it errors that str can't be converted to string, so I tried a few adjustments, and after getting errors about the & and such, I ended up with:
string operator=(str ing)
{
return ing.s;
}
Which gets the same error. Here's the full struct test program I'm using:
#include <iostream>
#include <string>
using namespace std;
struct str
{
string s;
string operator=(str ing)
{
return ing.s;
}
int last()
{
return s.length() - 1;
}
};
int main()
{
str ing {"Hello World!"};
string i = ing;
cout << i;
return 0;
}
If I could get the = assignment to work, I'd try to get << and such to work with str, too.
If that doesn't turn out to be possible, my fallback is just using a function like:
int last(string str)
{
return str.length() - 1;
}
Edit: For More Info
I was asked many times in the comments what my actual need is for this. In truth it’s just that it annoys me that it doesn’t have that member function. I’m surprised it wasn’t implemented long ago.
Thanks to the commenters I was able to come up with the diabolical workaround of overloading an operator to make a string able to subtract a function to output the result of a string being input to the function. I used - because I was thinking script notation: stringVariable -l or stringVariable -last. Then I can also just use #define to remove the need for the operator, making it stringVariable last() (“last()” instead of “last” because aesthetic).
Another option I figured out was reversing positions and using #define to make it last stringVariable, or #define in - to make it last in stringVariable. Although the simplest version of the operator function for this by far is just defining a negative string as the int output directly. Not that any of that is really better than just using the function normally, but I enjoyed learning about those features of C++.
The single answerer also consolidated much of the commenters advice and brought it to the next level to give me a more elegant version of the idea I had to create my own class with a string that could do all the string stuff and the extra member. However taking the advice of reexamining my needs I think perhaps ‘string’ isn’t the only option I have for a user input container. I definitely need the int output made by stringVariable.size() - 1 with whatever char array I use (since it’s used in mathematical equations), but maybe a vector or something else could do that already?
I was briefly told about vectors in my previous class, but we weren’t allowed to use them. Since this is for a simulated environment I’m doing on my own (that I might use for the basis of a game some day) I can use anything I want though. I also decided to pull an allnighter last night and just started reading about containers at random on cplusplus.com.
So I’m wondering if perhaps a list or deque could work too. I wasn’t really taught about anything other than string and hardcoded arrays (yet) though. I use the string to store the user’s input to simplify the process of avoiding unforeseeable crashing/errors that come from bad user inputs, then just translate the strings to whatever I need with various functions I've written.
creating a struct that is just a string and has the last() function as a member function
That will work just fine, if you don't mind implementing the interfaces needed to convert between std::string <-> str.
Also, be aware that std::string indexes use std::string::size_type, which is not int. size_type is an unsigned type, typically std::size_t. std::string defines an npos constant to indicate "no index", that is what your last() function should return if the std::string is empty, eg:
std::string::size_type last_index() const
{
return !s.empty() ? s.size() - 1 : std::string::npos;
}
But, if you really want to have last() return an int (ie, your std::string will never exceed 2147483647 characters):
int last_index() const
{
return static_cast<int>(s.size()) - 1;
}
With a struct, I'm not sure how (or if it's possible) to make it so I can make the variable assigned to the type automatically reference the string in it so that I don’t need to make a constant member call.
In short, no.
Based on the example I read, I tried:
str &operator=(const str &ing)
{
s = ing.s;
return s;
}
It needs to return a reference to the str object that is being assigned to, not the std::string member that was actually modified, eg:
str& operator=(const str &rhs)
{
s = rhs.s;
return *this;
}
But when I tried to test it by using = to copy a str variable to a string variable I could cout, it errors that str can't be converted to string
Correct, it can't by default. You need to define a conversion operator for that purpose, eg:
operator std::string() const
{
return s;
}
If I could get the = assignment to work, I'd try to get << and such to work with str, too.
Yes, you should, eg:
std::ostream& operator<<(std::ostream &out, const str &rhs)
{
return out << rhs.s;
}
If that doesn't turn out to be possible, my fallback is just using a function
That is a good idea, eg:
std::string::size_type last_index(const std::string &s)
{
return !s.empty() ? s.size() - 1 : std::string::npos;
}
Or:
int last_index(const str::string &s)
{
return static_cast<int>(s.size()) - 1;
}
Here's the full struct test program I'm using
Try this:
#include <iostream>
#include <string>
using namespace std;
class str
{
private:
string s;
public:
str() = default;
str(const string &s) : s(s) {}
str& operator=(const str &rhs)
{
s = rhs.s;
return *this;
}
operator string() const
{
return s;
}
string::size_type last_index() const
{
return !s.empty() ? s.size() - 1 : string::npos;
}
friend ostream& operator<<(ostream &out, const str &rhs)
{
return out << rhs.s;
}
};
string::size_type last_index(const string &s)
{
return !s.empty() ? s.size() - 1 : string::npos;
}
int main()
{
str ing {"Hello World!"};
cout << ing << endl;
cout << ing.last_index() << endl;
string i = ing;
cout << i << endl;
cout << last_index(i) << endl;
return 0;
}
I am a C++ novice and have an assignment using Oldie McOldSchool arrays and pointers. I have looked at this specific problem for about 8-12 cumulative hours now, kind of want to shove my face into a brick wall and don't really know what to think at this point. I am hoping from help from the experts here at SO!
I have the following class
#include <iostream>
#include <string>
using namespace std;
#include "mainclass.h"
#include "mysubobject1.h"
const string dataString[] =
{
"stringvalue,stringvalue,stringvalue,stringvalue,19,51,36,41,STUFF1",
"stringvalue,stringvalue,stringvalue,stringvalue,19,52,37,44,STUFF2",
"stringvalue,stringvalue,stringvalue,stringvalue,19,53,38,46,STUFF3",
"stringvalue,stringvalue,stringvalue,stringvalue,19,54,39,49,STUFF1",
"stringvalue,stringvalue,stringvalue,stringvalue,19,55,30,38,STUFF2",
};
MyObject* myObjectArray[5];
const string* dataArray[5];
int delimiterPositionArray[5][9];
string tokenArray[5][9];
Stuff stuff;
void main()
{
MainClass* mainClass = new MainClass();
dataArray[0] = &dataString[0];
dataArray[1] = &dataString[1];
dataArray[2] = &dataString[2];
dataArray[3] = &dataString[3];
dataArray[4] = &dataString[4];
/*Parse the contents of string into Token array. I have this working and can share if necessary but trimmed it out to keep this easy to look at */
for (int i = 0; i < 5; i++)
{
/* Logic to set the value of stuff goes here - it's very simple and trimmed for ease of reading */
mainClass->add(tokenArray[i][0], tokenArray[i][1], tokenArray[i][2], tokenArray[i][3], stoi(tokenArray[i][4]), stoi(tokenArray[i][5]), stoi(tokenArray[i][6]), stoi(tokenArray[i][7]), stuff);
}
cout << "TEST" << endl;
cout << mainClass->myObjectArray[0] << endl;
}
void MainClass::add(string string1, string string2, string string3, string string4, int int1, int int2, int int3, int int4, Stuff stuff)
{
MyObject myObject;
if (stuff == STUFF2) {
MySubObject1 myObject;
myObject.SetStuff(stuff);
}
myObject.SetString1(string1);
myObject.SetString2(string2);
myObject.SetString3(string3);
myObject.SetString4(string4);
myObject.SetInt1(int1);
int* intArray[] = { &int2, &int3, &int4 };
myObject.SetIntArray(intArray);
//Awful temporary array filling logic (which doent work properly, but works for the purpose of testing this problem)
if (myObjectArray[0] == nullptr)
{
myObjectArray[0] = &myObject;
}
else
{
if (myObjectArray[1] == nullptr)
{
myObjectArray[1] = &myObject;
}
/* ….until the array is filled */ }
}
And the question:
When I inspect this line of code from the main method in the mainclass.cpp in the VB debugger, all looks perfect. Token array contains what I expect:
mainClass->add(tokenArray[i][0], tokenArray[i][1], tokenArray[i][2], tokenArray[i][3], stoi(tokenArray[i][4]), stoi(tokenArray[i][5]), stoi(tokenArray[i][6]), stoi(tokenArray[i][7]), stuff);
I keep stepping through the code and get through the end of the add method. I see that everything looks fine by the time I reach the end of the add method. The strings and integers all appear to get set perfectly. I inspect the following line after the debugger runs over it and see everything looks great. Each array field has the data I expect in it. (the logic sucks and the data is the same for each array index, but that is for a later troubleshooting session :D)
myObjectArray[0] = &myObject;
After the add method runs, execution is deferred back to the main method and the following code outputs the results to the screen:
cout << "TEST" << endl;
cout << mainClass->myObjectArray[0] << endl;
This is where the problem is.... mainClass->myObjectArray[0] has empty values in all string properties and nothing is outputted for them (they contain "").... but the int properties have the proper output for some reason!
If anyone would have any insight into why the ints are available and the strings don't appear to be, I would be eternally grateful!
Thanks again!
Given you really didn't post all of your code, the code you did post shows one major issue, and could be the reason why your program behaves as it does.
In your MainClass::add() function, you're storing the addresses of local variables in the MainClass::myObjectArray array, and attempting to access these addresses from outside the add() function.
A synopsis of the code:
int main()
{
MainClass* mainClass = new MainClass();
//...
mainClass->add(...);
//...
cout << mainClass->myObjectArray[0] << endl; // <-- index 0 points to a garbage value
}
void MainClass::add(string string1, string string2, string string3, string string4, int int1, int int2, int int3, int int4, Stuff stuff)
{
MyObject myObject;
if (stuff == STUFF2) {
MySubObject1 myObject; // <-- Local variable
//...
int* intArray[] = { &int2, &int3, &int4 }; // <-- Another local variable
//...
myObject.SetIntArray(intArray); // <-- Storing address of local
//...
myObjectArray[0] = &myObject; // <-- Storing address of local
//...
}
When add() returns, those addresses will not be pointing to valid variables, since those variables no longer are valid since they are local variables.
So the fix is that you have to ensure that whatever pointers you place in your myObjectArray array, the lifetimes (scope) of those variables that are pointed to will last as long as myObjectArray.
A better solution to use an array of a type that stores "any" value such as an array of std::any.
In addition to this, you should attempt to reduce the unnecessary calls to new. For example, your main function starts off on the wrong foot:
int main()
{
MainClass* mainClass = new MainClass();
This could have simply been:
int main()
{
MainClass mainClass;
I've searched endlessly on SE for a logical explanation for why this is happening. It is probably something very simple that I've overlooked, however I cannot spot it and would really appreciate some assistance with this.
Last week I implemented a class to read the output of a system call from a .ini file and then find and store the required information into custom objects that are then stored in a vector inside a Config class. It is a Singleton config class storing a unique_ptr for each instance of my custom class that is created.
The thing is, when I implemented this last week on my laptop, I had zero issues reading and writing to my member vector and was able to get it working exactly how I needed it. Since pulling to my desktop computer, this vector, and any STL container that I use as a member of my class, throws a segmentation fault when I try to do anything on it, even get it's size.
I've tried to shorten the code below to only include sections that actually use this vector. I have replaced my config with A, and custom class with T, and no matter where I try to use my member container, or any other test STL containers that I add to the class, I get a segfault.
For the record, I am using Qt with C++11.
Update: This example breaks on line 50 of c.cpp when debugging, and anywhere that tries to call the vector.
Debug points to this line in stl_vector.h
// [23.2.4.2] capacity
/** Returns the number of elements in the %vector. */
size_type
size() const _GLIBCXX_NOEXCEPT
/*-> this line */ { return size_type(this->_M_impl._M_finish - this->_M_impl._M_start); }
main.cpp
#include "c.h"
int main(int argc, char *argv[])
{
C *c = C::getInstance();
delete c;
return 0;
}
t.h - Class stores information from file
#include <string>
class T
{
public:
T();
bool Active();
std::string getA();
void setA(std::string);
private:
std::string a;
};
t.cpp
#include "t.h"
T::T()
{
}
bool T::Active()
{
if(a == "")
{
return false;
}
return true;
}
std::string T::getA()
{
return this->a;
}
void T::setA(std::string newa)
{
this->a = newa;
}
c.h - Class stores T objects and parses file for information
#include "t.h"
#include <QDebug>
#include <vector>
#include <algorithm>
#include <iostream>
#include <memory>
#include <sstream>
#include <fstream>
class C
{
public:
static C* getInstance();
private:
C();
static C* instance;
static bool init;
std::vector<std::unique_ptr<T>> t_list;
void readLines(const std::string&);
};
c.cpp
#include "c.h"
bool C::init = false;
C* C::instance = nullptr;
C::C()
{
system("echo this is a test command > a.ini");
instance->readLines("a.ini");
}
C* C::getInstance()
{
if(!init)
{
instance = new C;
init = true;
}
return instance;
}
void C::readLines(const std::string &path)
{
T* new_t;
std::ifstream file(path.c_str());
if(!file.is_open())
{
qDebug() << "Unable to open " << path.c_str();
}
std::ofstream o("test.txt");
std::string line;
while(std::getline(file, line))
{
// Split string before searching
std::stringstream ss(line);
std::string seg;
std::vector<std::string> split;
std::string left, right;
// Search patterns
size_t find_a = line.find("a");
size_t del = line.find(':');
if(find_a != std::string::npos)
{
o << "test_Size: " << t_list.size() << std::endl;
if(new_t->Active())
{
T* temp = new_t;
std::unique_ptr<T> move_t(temp);
t_list.push_back(std::move(move_t));
}
o << "test: " << t_list.size() << std::endl;
std::string n;
// Check if previous ahas any null elements
// Split string to find a
n = line.substr(line.find("a "));
n = n.substr(n.find(" ", +2));
new_t->setA(n);
}
else
{
continue;
}
}
// Add last a
T* t = new_t;
std::unique_ptr<T> move_t(t);
//t_list.push_back(std::move(move_t));
o << "a: " << t_list.back().get()->getA() << std::endl;
o << t_list.size() << std::endl;
o.close();
file.close();
}
UPDATE after code change:
I see two things now: One is that new_t in C::readlines is never initialized, so this could break when new_t->Active() is called a bit later in the function. However, I believe that the main problem you're running into is in C::C(), where it says
instance->readLines("a.ini");
At this point in the execution, C::instance is not yet initialized -- you're only just constructing the object that would later be assigned to it. Because of this, this in the readlines call is invalid, and any attempt to access object members will cause UB. This latter problem can be fixed by just calling
readLines("a.ini");
in which case the currently constructed object (that will later be instance) is used for this. I have no idea what you want to happen for the first, though, so all I can say is: If you want to have a vector<unique_ptr<T>>, you will have to create objects of type T with either new T() or (arguably preferrably) std::make_unique<T>() and put them in there.
I'll also say that this is a rather ugly way to implement a singleton in C++. I mean, singletons are never really pretty, but if you're going to do it in C++, the usual way is something like the accepted answer of C++ Singleton design pattern .
Old answer:
The problem (if it is the only one, which I cannot verify because you didn't provide an MCVE) is in the lines
T move_t = new_T;
std::unique_ptr<Adapter> ptr_t(&move_t); // <-- particularly this one
m_ts.push_back(std::move(ptr_t));
You're passing a pointer to a local object into a std::unique_ptr, but the whole purpose of std::unique_ptr is to handle objects allocated with new to avoid memory leaks. Not only will the pointer you pass into it be invalid once the scope surrounding this declaration is left, even if that weren't the case the unique_ptr would attempt to delete an object that's not on the heap at the end of its lifecycle. Both problems cause undefined behavior.
To me, it looks as though you really want to use a std::vector<T> instead of std::vector<std::unique_ptr<T>>, but that's a design issue you'll have to answer yourself.
Answering my own question here. I am trying to call a member variable from within the constructor of the object that holds it, so the vector I am trying to access is not yet instantiated and doesn't exist in memory. That is what causes the Segmentation fault to occur, I am trying to access memory that is not allocated yet, hence any call acting on any member of my C class was causing this issue.
I fixed this problem by adding a public function to the class that then calls the private readLines() function. I call that public function from the object that will take ownership of it, and since this occurs after it has been instantiated, the memory is accessible and the problem disappears.
Suppose that I have to call same method for each member of a vector contained in a class.
If element-i of the vector has a certain value, I have to modify it.
I've max 10 element in this vector.
What is the best way to do?
- Call a method with an optional parameter?
- Or call a method with an if-else statment inside?
class A {
public:
A();
void doSomething(const string& s) {
if(s=="foo") {
std::cout << s;
} else {
std::cout << s << ".dat"
}
}
void doSomethingDef(const string& s, const string& v = "") {
std::cout << s << v;
}
private:
std::vector<std::string> list_;
}
int main() {
A a;
}
/* Constructor with method 1 */
A::A() {
std::vector<std::string>::iterator i = list_.begin();
for(; i != list_.end(); ++i) {
this->doSomething(*i);
}
}
/* Constructor with method 2 */
A::A() {
this->doSomethingDef(list[0]);
this->doSomethingDef(list[1]);
this->doSomethingDef(list[2]);
this->doSomethingDef(list[3]);
this->doSomethingDef(list[4], ".dat");
this->doSomethingDef(list[5], ".dat");
this->doSomethingDef(list[6]);
this->doSomethingDef(list[7]);
this->doSomethingDef(list[8]);
this->doSomethingDef(list[9]);
}
If you have a max of 10 elements, I'm going to claim that performance is completely irrelevant anyway.
Furthermore, until you have proven that performance really matters, method 1 is so much more readable that you should prefer it anyway.
Finally, because of the way cout operations work, I would guess that in this little example, method 2 is actually slower, because it's faster to do a branch and a comparison with a fixed string than doing an additional call to a formatted output function.
In C++11 your constructor with method 1 could be written as:
A::A()
{
for(const auto & listElement : list_)
{
this->doSomething(listElement);
}
}
Performance and readability and a bit more generic to boot. Or you could do it with a std::for_each and a lambda function which may trigger a compiler with optimizations turned on to unroll that loop for you.
A::A()
{
for_each(begin(list_), end(list_),[this](const std::string & listElement)
{
doSomething(listElement);
});
}
If you decided to use something similar to your second method (not that I'm advising it, just considering how to do it if you were to), I'd strongly consider using overloading instead of a default parameter:
void doSomethingDef(const string& s) {
std::cout << s;
}
void doSomethingDef(const string &s, const string &v) {
std::cout << s << v;
}
With a default parameter, you're still creating a temporary string and passing it as the second parameter, then making all the iostreams calls to insert that string into the stream even though it has no effect. By using overloading instead, you avoid all the processing necessary to create, pass, and insert the second string (except when you really have a second string to display, of course).
Mixing that with I/O (and only writing 10 strings anyway) probably covers up most of the benefit from this, so it'll probably be hard to even measure, not to mention notice in real life. On the other hand, if you were generating a lot of strings and (for example) depositing the output in memory instead of writing it to output, the difference could start to become substantial.
I'm quite new to C++. I've been trying to figure this out for days - there'll be an easy solution no doubt but I haven't been able to find it (after much googling)! My problem is this:
I'm trying to create a class with a member function that reads in characters from a file and stores them in an array. I want to be able to create multiple objects (not sure how many - decided by the user), each with their own arrays filled with characters taken from different files. I think I've managed to do that. How would I then go about accessing the object's array in main?
The code I'm working on is long and messy but something along these lines (char.txt contains simply '12345' in this case):
#include <iostream>
#include <fstream>
using namespace std;
class Something{
public:
void fill_array(char array_to_fill[]){
char next;
ifstream input;
input.open("chars.txt");
input.get(next);
while(!input.eof())
{
for(int i = 0; i < 6; i++)
{
array_to_fill[i] = next;
input.get(next);
}
}
}
};
int main()
{
Something* something = new Something[1];
char array_to_fill[5];
something->fill_array(array_to_fill);
//I'd like to be able to access the array here; for example - to cout the array.
return 0;
}
Apologies if a) my terminology is wrong b) my code is rubbish or c) my question is stupid/doesn't make sense. Also I should add I haven't learnt vectors yet and I'm not supposed to use them for the program I'm making. Any help would be much appreciated. Cheers!
Your class does not store the array at all. It is simply a holder for a method. You probably want something like this, where each instance of the class holds the array. (I changed it to std::string since they are nicer to work with.)
class Something
{
private:
std::string data;
public:
void fill_data( const std::string& filename )
{
ifstream file( filename );
file >> data;
file.close();
}
std::string get_data() const
{
return data;
}
}
int main()
{
std::vector<Something> my_things;
my_things.push_back( Something() );
my_things[0].fill_data( "chars.txt" );
cout << my_things[0].get_data() << std::endl;
my_things.push_back( Something() );
my_things[1].fill_data( "another_file.txt" );
cout << my_things[1].get_data() << std::endl;
}
Since you are using C++, not C, get used to writing C++ code instead of C. (std::vector instead of C arrays (for unknown length arrays), std::string instead of char*, etc).
I think your question is too general for the format of stack overflow, but what you want in this case is to either create a public member, or create a private member with setters and getters.
class Something
{
public:
std::string m_string;
}
int main()
{
Something A;
A.m_string = "toto";
cout << A.m_string;
return 0;
}
Put a string for convenience (you could use a const char* but you will have to understand what is the scope to know when it will not be accessible anymore and you are not quite there yet) and there may be typos since I typed this from a phone.
If you really want to access the chars themselves, pass a char* with a size_t for the length of the array or use std::array if possible.
Right now the method fill_array is creating a local copy of array_to_fill, so any changes that you make to array_to_fill only happen in the local method. To change this, pass by pointer. This way the pointer gets copied instead of the whole array object. I didn't test this but it should look more like this:
void fill_array(char* array_to_fill){
...
}
You don't need to change anything in the main method.
To actually access the elements you can use [] notation. I.e. cout << array_to_fill[0] in the main method.
Edit: I think that change should work.