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.
Related
After a pointer is initialized, do you have to use the * dereference operator to call the pointer in a condition?
Example:
int main()
{
int var = 10;
int *ptr = &var;
if(ptr) // does this need to be if(*ptr) ???
{.......}
}
And can I have a short explanation as to why?
Thank you.
if (ptr)
check if the pointer is not Null but
if (*ptr)
check if the value it points to is not zero (in this example is 10)
So for checking the value you shoud add *.
It depends on what you want to do.
if(ptr) checks if the pointer value is nullptr or not. Note that this is shorthand for if(ptr != nullptr).
if(*ptr) checks if what the pointer points to is nullptr (or 0) - and in that case, since you dereference (follow) the pointer to answer the question, the pointer itself had better not be nullptr in that case.
First of all, a pointer is only a variable. However, there are different contexts in which you can use it.
As any other variable you can access the pointers content (which is the adress of the underlying memory) as follows:
int i = 1;
int * p = &i;
std::cout << p << std::endl
this would output the adress of i since this is what is stored in p
If you however want to access the content of the underlying memory (the value of i), you need to dereference the pointer first by using the * operator:
std::cout << *p << std::endl;
This would print the value of iso 1.
of course you can also access the pointer's adress (since the adress of i is a numeric value as well and needs to be stored somewhere too):
std::cout << &p << std::endl;
That would output the adress of p so the adress where the adress of i is stored :)
As a little example try to run this code:
#include <iostream>
int main() {
int i = 1;
int * p = &i;
std::cout << "Value of i(i): " << i << std::endl
<< "Adress of i(&i): " << &i << std::endl
<< "Value of p(p): " << p << std::endl
<< "Dereferenced p(*p): " << *p << std::endl
<< "Adress of p(&p): " << &p << std::endl
<< "Dereferenced adress of p(*(&p)): " << *(&p) << std::endl;
}
Im trying to understand the delete operator in c++.
I could understand the logic behind using pointers and new operator, yet I understood that "The delete operator eliminates a dynamic variable and returns the memory that the dynamic variable occupied to the freestone." p517, Problem solving with C++ 9th edition.
which, I think doesn't align with the third cout statement. and I expected that the third cout statement to be sth similar to the first one.
int main() {
int *p1;
cout << "p1 address: " << &p1 << " and points to the address "<< p1 << " which has the value: " << *p1<< endl;
p1 = new int;
cout << "p1 address: " << &p1 << " and points to the address "<< p1 << " which has the value: " << *p1<< endl;
delete p1;
cout << "p1 address: " << &p1 << " and points to the address "<< p1 << " which has the value: " << *p1<< endl;
cout << endl;
return 0;
}
I would appreciate any explanation :))
delete doesn't have to change the memory your pointer points to. What it actually does is implementation specific.
What delete needs to do is to deconstruct any object at the given address and return the associated memory to the allocation pool. Some debugger might overwrite the value of a variable when freed, but for trivial types no special deconstruction needs to take place - the memory can be returned to the pool as-is. The pointer isn't changed either: after delete p we call p a dangling pointer that holds an address to freed memory. All access through that pointer is undefined behaviour.
Since handling raw pointers and especially dangling pointers is error prone, it's good to know the C++ smartpointers, e.g. unique_ptr:
std::unique_ptr<int> p; // initialised to nullptr
p = std::make_unique<int>(13); // new int with value 13
p = std::make_unique<int>(37); // deleted previous int, assigned new int with value 37
// optional (when p goes out of scope its pointee is deleted automatically)
p.reset(); // deleted the int and reset p to nullptr
I have the following code:
#include <iostream>
using namespace std;
int main ()
{
int myvar = 5;
int * p;
cout << "Hello2" << endl;
*p = myvar;
cout << "Hello" << endl;
cout << p << endl;
//cout << &myvar << endl;
}
I know I am not doing the right thing by not initializing the pointer. I was just playing with pointers and noticed this. The issue is when I comment out the last line, the program executes normally. But as soon as I uncomment the line, I get a segmentation fault. I don't know why printing address of myvar is causing this? Has myvar been modified in any way because of pointer dereferencing? I am using C++11.
int* p;
*p = myvar;
You are creating an uninitialized pointer and then derferencing that pointer. This has undefined behavior because p has to point to something for it to be derferenced correctly. Therefore your program's behavior can't be reasoned with.
Segmentation Fault occurs when trying to access a virtual memory address that has no read permissions.
In your case, the local variable p holds uninitialized garbage from the stack.
you are dereferencing a memory address that might not be readable(e.g no read permissions, hence the segmentation fault when trying to access it).
I'm not entirely sure the purpose of your snippet, but the following code will work, and perhaps it will help:
int myvar = 5;
int *p = nullptr;
p = &myvar;
cout << myvar << endl;
cout << &myvar << endl;
cout << p << endl;
cout << *p << endl;
(Note: I used two lines for setting 'p' because that is how you did it in your snippet. You could easily just use: int *p = &myvar; )
Anyway, there are scope issues here as p will only be valid as long as myvar is in scope; however, this does illustrate the basics of pointers. myvar and *p will return the same value (the value being pointed to), and &myvar and p will return the same value (the location of value in memory.)
basic syntax of pointers: *ptr= &a
here &a will return the memory address of variable a and *ptr will store value of variable a
I want to ask, is it possible to make a pointer return a value from a given memory address? if yes what's the syntax
Yes, you can construct a pointer that refers to some arbitrary address in memory, by initialising the pointer with the address directly, instead of with an expression like &a:
int* ptr = (int*)0x1234ABCD; // hex for convenience
std::cout << *ptr;
Be careful, though, as it is rare that you know such a memory address exactly.
The cast (int*) is required as no implicit conversion exists between int and int*.
Yes. Use the dereference operator *.
For example;
int * a = new int;
int * b = new int;
*a = 5;
// Now a points to a memory location where the number 5 is stored.
b = a; //b now points to the same memory location.
cout << *b << endl; ///prints 5.
cout << a << " " << b << endl; //prints the same address.
int * c = new int;
c = *a;
// Now c points to another memory location than a, but the value is the same.
cout << *c << endl; ///prints 5.
cout << a << " " << c << endl; //prints different addresses.
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.