0

there is a prototype of a function in my fuu.h. I want to pass default values if there

void MyFunction(
    int iError = 0,
    std::string * MyProblemString = ""
    );

// Some attemts:

void MyFunction(
    int iError = 0,
    std::string * MyProblemString = std::string{""};    // does not work to, complains about missing '*' 
    );

void MyFunction(
    int iError = 0,
    std::string * MyProblemString = &std::string{""};   // does not work to, refering address to temporary value
    );

void MyFunction(
    int iError = 0,
    std::string * MyProblemString = *std::string{""};   // does not work to, overloaded operator not known
    );

void MyFunction(
    int iError = 0,
    std::string * MyProblemString = "";     // could not convert ‘""’ from ‘const char [1]’ to ‘std::__cxx11::string* {aka std::__cxx11::basic_string<char>*}’
    );

in my c-file is written:

void MyFunction(
    int iError,
    std::string * MyProblemString,)
{
    // do some stuff
}

With the int it's working fine. How can I make the same thing with the string?

There are some examples with other constructions, but passing a pointer does not work. const reference default-value

thx

Community
  • 1
  • 1
Cutton Eye
  • 3,207
  • 3
  • 20
  • 39
  • You are attempting to initialize a pointer to a `std::string` with a `std::string`. That, obviously, is not going to happen. I believe you're missing the fundamental understanding of what are objects, and what are pointers, in C++. You need to study the basic concepts a little bit more. – Sam Varshavchik Nov 18 '16 at 03:04
  • ok, but have you a solution for the problem? Can you tell me, which topic to look? Is it possible? ( Jear, I know those are random trys). I'm able to work with double pointers etc. How ever, Could also pass a const cahr[] and it would work. – Cutton Eye Nov 18 '16 at 03:11

2 Answers2

3

I don't think you understand what pointers do. I'll try to help.

Pointers

int number;      // An int
int * pointer;   // A valid pointer to an int
int* pointer;    // Also a valid pointer to an int
int *pointer;    // Also a valid pointer to an int

"number" is a named variable of type integer with a chunk of memory big enough to store an int assigned to it. This chunk of memory is given a memory address.

Pointers are basically like an int, except the number they store is the memory address of another variable - in your case, "number".

The & operator will give you the memory address of the variable you use it on.

&number 

This will give you the memory address of your int "number".

pointer = &number;  // Pointer now contains the memory address of "number"

Now if you try to use pointer like an int, it will give you the address of "number", not its contents. To access the contents of whatever your pointer is pointing at, prefix it with *.

    void main()
{
    int number = 56;            

    int* pointer = number;      // INVALID: Pointer now pointing at memory location "56"
    int* pointer = &number;     // Valid: Pointer now pointing at memory location of number

    int* pointer;               // DANGEROUS, DO NOT LEAVE HANGING POINTERS -- leads to memory access violations

    int *pointer = nullptr;     // Safely initialise unused pointer
    int size = 32;
    pointer = new int;          // Allocates a block of memory the size of 1 int. Pointer now points at this memory
    pointer = new int[size];    // Allocates an array of 32 ints to pointer. Pointer now points to this block of memory
    pointer = new int[8];       // Allocates another array to pointer. Pointer now points at the new array, old array has nothing pointing at it and is lost in memory!
                                // This is a memory leak. AVOID MEMORY LEAKS AT ALL COSTS, they can produce some of the hardest-to-find bugs you'll come across

    delete pointer;             // Deletes chunk of memory the size of 1 int at the memory pointer is pointing at
    delete[] pointer;           // Deletes array of memory following the location pointer is pointing at

    // IMPORTANT: ALWAYS use delete with new, delete[] with new[]
    // IMPORTANT: NEVER use new or new[] without its delete counterpart, or you will encounter memory leaks

    // USEFUL:
    if (pointer != nullptr)
    {
        // Do stuff
    }
    // Doing this will ensure you don't act upon memory you aren't supposed to mess with


    // Print these to console to gain a better understanding.
    std::cout << number << std::endl;
    std::cout << &number << std::endl;
    std::cout << pointer << std::endl;
    std::cout << *pointer << std::endl;

    system("pause");
}

Pay attention to the output:

Output on my machine (the address will vary when you run it):

56           // number
0035F7E0     // &number
0035F7E0     // pointer
56           // *pointer

Note that "&number" and "pointer" print the same thing

You can use & and * to assign pointers to anything, including pointers to other pointers to other pointers to other pointers to whatever the hell you want. It gets messier the deeper you go with things like that, but the point is (pun unintended) pointers are one of the most versatile and handy (but also dangerous -- MEMORY LEAKS, ACCESS VIOLATIONS, AHHH) things to use in C++.

Hope this helped, post a reply to this answer if you don't understand or if this didn't help you understand your problem.

Just Jake
  • 66
  • 2
1

The problem you are having is because you can't give a default value to a pointer without dealing with the memory the pointer is supposed to point to. If you use a std::string instead of a pointer to std::string then you can use the simple string literal syntax as in MyFunction().

If you need to pass a pointer to a string, because you are planning to manipulate the string or for some other purpose, you can give the string the default value of NULL. Since NULL does not point to any memory, this is a perfectly sane default for a pointer. Then you can check for this value, and allocate a new std::string in that special case. That is what I am doing in MyFunction2.

HOWEVER if you allocate memory, you must free that memory somewhere. In my example, I am freeing the memory inside of MyFunction2 only if I also created it. If the value was supplied, I am not freeing the value, but rather leaving that up to the calling function. How you manage memory will depend on your use case, but don't forget about this crucial step.

#import <iostream>

void MyFunction(
    int iError = 1,
    std::string MyProblemString = std::string(""))
{
  std::cout << "\tiError = " << iError << ", and MyProblemString = " << MyProblemString << std::endl;
}

void MyFunction2(
    int iError = 1,
    std::string * MyProblemString = NULL)
{
  bool shouldFree = MyProblemString == NULL;
  if (shouldFree){
    MyProblemString = new std::string("");
  }
  std::cout << "\tiError = " << iError << ", and MyProblemString = " << *MyProblemString << std::endl;

  if(shouldFree){
    delete MyProblemString;
  }
}

int main(){
  std::string * test = new std::string("test");

  std::cout << "Testing with MyFunction:" << std::endl;
  std::cout << "\tTest default arguments:" << std::endl;
  MyFunction();

  std::cout << "\tTest only first argument:" << std::endl;
  MyFunction(0);

  std::cout << "\tTest both arguments" << std::endl;
  MyFunction(2, *test);

  std::cout << std::endl;

  std::cout << "Testing with MyFunction2:" << std::endl;
  std::cout << "\tTest default arguments:" << std::endl;
  MyFunction2();

  std::cout << "\tTest only first argument:" << std::endl;
  MyFunction2(0);

  std::cout << "\tTest both arguments" << std::endl;
  MyFunction2(2, test);

  delete test;
}
Mobius
  • 2,871
  • 1
  • 19
  • 29
  • dear @Mobius I thank you for your time and detailed words and exampels. This is the answer I was looking for. I'm going to use this not for allocating dynamic. Just want to use this function with or without additional error-informations, but don't want to overload it because of redundant code. But anyways, thank for reminding me at the unfreed memory. I'm sure valgrind likes you =). Thx again! – Cutton Eye Nov 18 '16 at 05:02