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
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.
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;
}
Related
I ask you questions because there is something I don't understand while studying dynamic allocation in C++.
Can I delete "St" and use "ptr" instead if I move the address stored in St to another pointer "ptr" when the dynamically allocated memory is pointed by the St pointer?
If I delete the "St" dynamic allocation, can I move the address to another pointer and delete the "St" immediately because the allocated space does not disappear but disconnects the pointer "St" from the space?
Below is the code I was writing.
Student is a structure.
int main()
{
case 1:
{
Student* ptr = NULL;
Student* St = new Student[10];
ptr = St;
delete[] St;
St = NULL;
break;
}
case 2:`enter code here`
{
printdata(ptr);break;
}
}
Once you've called delete[] on the pointer you get back from new Student[10], the value of that pointer is indeterminate. Both St and ptr are exactly that, but you reassign St. (Since C++11, use nullptr rather than NULL.)
The behaviour of dereferencing the pointer you get back from new Student[10] following the delete[] is undefined.
You can’t use memory you just freed. Memory at that address might still be usable (event till program closes), but there is no guarantee and program might use it for something else.
Can I delete "St" and use "ptr" instead if I move the address stored
in St to another pointer "ptr" when the dynamically allocated memory
is pointed by the St pointer?
If St points toward your array, you can make ptr point toward it as well, but it is not a transfer. What you actually transfer is the adress of the object you are pointing to. The 2 pointers will point toward the same object.
If you delete the object with delete[] (you delete the object, not the pointer), then the 2 pointers will point toward nothing. So what you actually want to do here is make ptr point toward the same object, and then make St point toward null.
Student* ptr = NULL;
Student* St = new Student[10];
ptr = St;
St = NULL;
Edit : If it may help you understand, here is what you can display ...
int x = 4;
int* p = &x;
cout << "x = " << x << " value of x." << endl;
cout << "&x = " << &x << " adress of x." << endl;
cout << "*p = " << *p << " the value of what p points to." << endl;
cout << "p = " << p << " the actual value of p which is the adress of x." << endl;
I've tried to create a minimal example of my problem. I'm trying to check if the address of an void pointer is NULL or not. The address should be overgiven by constructing the class, and should be const. I wrote the class below.
MyPointer.h:
public:
MyPointer(const void* activeApp) : m_activeApp(activeApp){
std::cout <<"adresse on construction: " << m_activeApp << std::endl;
};
MyPointer.cpp:
void printAdress();
private:
const void* m_activeApp;
};
The Methode "printAdress" should be able to print the correct address of the given pointer.
int main(void){
void* p_activeApp = nullptr;
std::cout << p_activeApp << std::endl;
MyPointer myPointer(p_activeApp);
std::cout << "Should be 0: " ;
myPointer.printAddress();
p_activeApp = new(bool);
std::cout << "Should be anything: ";
myPointer.printAddress();
}
void MyPointer::printAddress() {
std::cout << this->m_activeApp << std::endl;
};
Of course it doesn't work, because the m_activeApp still points to NULL, but how can I change this?
If you want to change what myPointer.m_activeApp points to, you have to set the pointer to a different value, simple as that. This pointer and p_activeApp are two distinct, independent pointers. Changing one does not change the other.
What you can do is to make one pointer a reference to the other pointer instead. Then, changing one would also change the other. This will work, though be warned, it won't be good programming style.
Pointers are integers (representing a memory location), so imagine void* to be a number. You set p_activeApp to 0, then you construct a MyPointer, and its internal pointer is set to 0.
Then you change the first number by using the new operator, p_activeApp now gets a value (to that new memory address), but there's no reason for m_activeApp to also change. It still points at 0, no matter what p_activeApp changes to.
I fixed it like this:
public:
MyPointer(void** activeApp) : m_pp_activeApp(activeApp) {
std::cout <<"address on construction: " << *m_pp_activeApp << std::endl;
};
void printAddress();
private:
void** m_pp_activeApp;
};
int main(void){
void* p_activeApp = nullptr;
void** pp_activeApp = &p_activeApp;
MyPointer myPointer(pp_activeApp);
std::cout << "Should be 0: " ;
myPointer.printAddress();
p_activeApp = new(bool);
std::cout << "Should be anything: ";
myPointer.printAddress();
}
void MyPointer::printAddress() {
std::cout << *m_pp_activeApp << std::endl;
};
What happens when I do this? When I remove the first initialization to "boo1", it prints boo2 but now it still prints nothing. Does this mean that the pointer allocate a random memory and assign "boo1" value to it and now I can't access it or what?
string *p;
*p="boo1";
p=new string;
*p="boo2";
cout << *p; //prints nothing
line 1: "p" contains random value, i.e. refers to random memory address.
line 2: random memory block referred by "*p" is interpreted as string instance. This instance is assigned by "boo1".
Try so:
string *p = new string;
*p = "boo1";
cout << *p << '\n';
*p = "boo2";
cout << *p << '\n';
delete p;
Remember that:
std::string is not the same as stupid char[] array!
All pointers must be assigned before usage!
All "new" must have corresponding "delete"!
If you declare a string as pointer ( string *p ), you must allocate memory for it,
so the correct way to do the job is:
string *p = new string;
*p = "boo1";
cout << *p << '\n';
*p = "boo2";
cout << *p << '\n';
The previous answers are correct, however why not using a reference, it seems more convenient in your case.
Something like :
std::string p;
p = "boo1";
std::cout << p << std::endl;
p = "boo2";
std::cout << p << std::endl;
Regards,
Michel.
I have a function which returns a const char*
const char* SayHi()
{
string data="Mustafa Hi";
const char* cptr=data.c_str();
return cptr;
}
int main()
{
cout<<SayHi()<<endl;
return 0;
}
But output is not :
Mustafa Hi. It is null.
If i define data variable as global like
string data;
const char* SayHi()
{
data="Mustafa Hi";
const char* cptr=data.c_str();
return cptr;
}
int main()
{
cout<<SayHi()<<endl;
return 0;
}
Output is Mustafa Hi.
But for const int* this works;
const int* aMethod()
{
int* aVar=new int(111);
const int* acstPtr=aVar;
return acstPtr;
}
int main()
{
cout<<*aMethod()<<endl;
return 0;
}
Output : 111
or
const int* aMethod()
{
int aVar =111; //in stack
const int* acstPtr=&aVar;
return acstPtr;
}
so why not null?
The problem with your first implementation is that you return a pointer to temporary memory. Because the 'string data' variable is only defined within the scope of that function, when the function goes away, the pointer that you just returned is now pointing to free'd memory. In your case, it must be being overwritten with all zeros. That is why you are seeing NULL.
Because in C++ objects have a lifetime. In your first example the string no longer exists once you exit the function. Therefore it's an error to return a pointer to that string's data.
You need to understand that "string data" inside of SayHi is a local variable. When the function exits local variables are destroyed.
To do what you're trying to do you either have to create the storage for the string so that it is not local to SayHi, either in main and pass it in or on the heap. Perhaps you'd like SayHi to return a reference.
Try the code below. If you want to return a pointer to a local variable, you need to use a static keyword. All local variable will be free after it exist the function. That is the reason are not able to get the string properly return.
const char* SayHi()
{
static string data="Mustafa Hi";
const char* cptr=data.c_str();
return cptr;
}
But output is not : Mustafa Hi. It is null.
It could be anything. Issue is with returning the member variable (const char *) of a local object (string), which will be cleaned once we come out of the enclosing curly brace. Output is undefined in such cases. On few compilers you may even get the desired output if the the memory that was released was not reallocated.
It works for global variable because they span throughout the life time of the program and is not cleaned up after the control exits SayHi()
const int* this works;
This is dynamic memory allocation as against the stack allocation earlier. Unlike stack allocation (creating local object), with heap allocation (using new) you have the memory and the value until you delete the memory explicitly.
To replicate the first scenario with int, your code should be something like,
const int* aMethod()
{
int aVar=111; // changed from pointer to local variable. Heap to stack
const int* acstPtr= &aVar; //Returning the address for local variable. Which will be freed at the enclosing curly brace.
return acstPtr;
}
But again, output is undefined when you deal with pointers whose memory is already freed (dangling pointer)
Local variables are created on the "stack", which have a lifetime of the scope they exist in. In particular, what is happening in your original case:
string data="Mustafa Hi";
const char* cptr=data.c_str();
return cptr;
is complicated by the fact thatstd::string is an object with a destructor. Prior to C++11, it may have stored the string without the terminating zero unless you called c_str(). Internally, it contains a pointer and a size value and perhaps also a capacity value. It allocates memory to store the string. Think of (pre-C++11) std::string like this:
class String {
char* m_ptr;
size_t m_length;
size_t m_alloc;
public:
String() : m_ptr(nullptr), m_length(0), m_alloc(0) {}
String(const char* src) {
size_t length = strlen(src);
m_ptr = new char[length];
m_alloc = m_length;
memcpy(m_ptr, src, length); // not including the \0
}
const char* c_str() {
if (m_length == 0)
return nullptr;
if (m_alloc > m_length) // we're null terminated
return m_ptr;
char* newPtr = new char[length + 1];
memcpy(m_ptr, newPtr, length);
delete [] m_ptr;
m_ptr = newPtr;
m_ptr[length] = '\0';
++m_alloc;
return m_ptr;
}
~String() {
#ifdef _DEBUG
if (m_ptr) m_ptr[0] = 0;
#endif
delete [] m_ptr;
}
};
Your function is taking the address of an instance of this object, then returning that address. The next thing that happens is that the instance goes out of scope and calls it's destructor -- it was on the stack and immediately after your code, so the stack location it was in is now available for use by whatever code gets called next.
Take a look at the following sample (live demo: http://ideone.com/wAcY3B)
#include <iostream>
int* getInt1(int input)
{
int i = input;
std::cout << "created 'i' at " << (void*)&i << std::endl;
int* ptr1 = &i;
return ptr1;
}
int* getInt2(int input)
{
int* ptr3 = new int(input);
return ptr3;
}
int main()
{
int i = 0;
std::cout << "i is on the stack, it's address is " << (void*)&i << std::endl;
int* ip = new int(1);
std::cout << "ip is on the heap, it's address is " << (void*)ip << std::endl;
int* p1 = NULL;
int* p2 = NULL;
int* p3 = NULL;
// force the pointers to be assigned locations on the stack by printing them.
std::cout << "created p1(" << &p1 << "), p2(" << &p2 << ") and p3(" << &p3 << ")" << std::endl;
p1 = getInt1(10101);
std::cout << "p1(" << &p1 << ") = " << (void*)p1 << " -> " << *p1 << std::endl;
p2 = getInt1(20202);
std::cout << "p2(" << &p2 << ") = " << (void*)p2 << " -> " << *p2 << std::endl;
// but more importantly
std::cout << "p1(" << &p1 << ") = " << (void*)p1 << " -> " << *p1 << std::endl;
p3 = getInt2(30303);
std::cout << "p3(" << &p3 << ") = " << (void*)p3 << " -> " << *p3 << std::endl;
std::cout << "p2(" << &p2 << ") = " << (void*)p2 << " -> " << *p2 << std::endl;
std::cout << "p1(" << &p1 << ") = " << (void*)p1 << " -> " << *p1 << std::endl;
}
Output looks like this:
i is on the stack, it's address is 0xbfb49a90
ip is on the heap, it's address is 0x9b83008
created p1(0xbfb49a94), p2(0xbfb49a98) and p3(0xbfb49a9c)
created 'i' at 0xbfb49a6c
p1(0xbfb49a94) = 0xbfb49a6c -> 10101
created 'i' at 0xbfb49a6c
p2(0xbfb49a98) = 0xbfb49a6c -> 20202
p1(0xbfb49a94) = 0xbfb49a6c -> -1078682988
p3(0xbfb49a9c) = 0x9b83018 -> 30303
p2(0xbfb49a98) = 0xbfb49a6c -> -1078682988
p1(0xbfb49a94) = 0xbfb49a6c -> -1078682988
Because the stack pointer doesn't change between calls to "getInt1()" it's local variable instances are in the same location, but if you call some other random functions in-between assignments, they will use the same stack location and your pointed-to-values will be lost.
I just learned the difference between the stack and the heap. After creating a function which will dynamically allocate memory on the heap for me, I return the pointer and display (in and out of the function) the address and value of each pointer.
The values are the same, which I expected, but the addresses to the same chunk of memory on the heap are different, which I did NOT expect.
Why? Shouldn't pHeap2 and pTemp point to the same address?
#include <iostream>
using namespace std;
int* intOnHeap(); // returns an int on the heap
int main()
{
int* pHeap = new int; // new operator allocates memory on the heap and returns its address
// 'new int' allocates enough memory on heap for one int and returns the address on the heap for that chunk of memory
// 'int* pHeap' is a local pointer which points to the newly allocated chunk of memory
*pHeap = 10;
cout << "*pHeap: " << *pHeap << "\n\n";
int* pHeap2 = intOnHeap();
cout << "pHeap2:\n-----------" << endl;
cout << "Address:\t" << &pHeap2 << "\n";
cout << "Value:\t\t" << *pHeap2 << "\n\n";
cout << "Freeing memory pointed to by pHeap.\n\n";
delete pHeap;
cout << "Freeing memory pointed to by pHeap2.\n\n";
delete pHeap2;
// get rid of dangling pointers
pHeap = 0;
pHeap2 = 0;
system("pause");
return 0;
}
int* intOnHeap()
{
int* pTemp = new int(20);
cout << "pTemp:\n-----------" << endl;
cout << "Address:\t" << &pTemp << "\n";
cout << "Value:\t\t" << *pTemp << "\n\n";
return pTemp;
}
Output:
*pHeap: 10
pTemp:
-----------
Address: 0042FBB0
Value: 20
pHeap2:
-----------
Address: 0042FCB4
Value: 20
Freeing memory pointed to by pHeap.
Freeing memory pointed to by pHeap2.
Press any key to continue . . .
You are reporting the address of the pointers, not the address that the pointer is pointing to. Of course the address of the pointer will be different for pTemp and pHeap2; these are different pointers that happen to be pointing to the same address in memory. Remove the & prefixing pTemp and pHeap2 to see the results that you are expecting.
The picture is something like this:
0042FBB0 0042FBC0 0042FCB4
------------ ------ ------------
| 0042FBC0 |------>| 20 |<------| 0042FBC0 |
------------ ------ ------------
pTemp pHeap2
Here you have that &pTemp is 0042FBB0 and &pHeap2 is 0042FCB4. I made up an address for the address that pTemp and pHeap2 are pointing to (of course, the results could vary from run to run anyway) and if you remove the & prefixing pTemp and pHeap2 then you would see 0042FBC0 printed instead in each case.
Yes, pTemp and pHeap2 should be the same. But &pTemp and &pHeap2 are different. This is because the & operator returns a pointer to it's operand. So pTemp is a pointer to an int, while &pTemp is a pointer to a pointer to an int.
&pHeap2 doesn't return the value of the pointer, it returns the address of the pointer. That's because of the &, which in this context means "the address of".
i.e. at 0042FCB4 in memory, there's a pointer pointing to 0042FBB0 (i.e. in a big-endian environment, you'd see 00 42 FB B0 at 0042FCB4).