This question already has answers here:
Is returning a pointer to a static local variable safe?
(7 answers)
Closed 8 years ago.
The following case makes more confuse to me. As far as I know, local variables don't return by pointers or reference. for example
char * foo()
{
return "Hello world";
}
int* fooo() {
static int i = 100;
return &i;
}
What would happen in both cases ?
String literals are stored statically and of course the static int i is static too. You can return pointers to static variables from functions because they are not local variables, and they are not destroyed when you exit the function as stack allocated variables do. On the other hand, your first example should return a const char *,
From the C++ standard section lex.string:
A string literal ... has type "array of n const char" and static storage duration (basic.stc), where n is the size of the string as defined below, and is initialized with the given characters...
The first code will not compile. You can cast the string to char array and return back. The second code will compile, but your variable will go out of scope. So the reference you will have when the function returns will not be valid anymore. It is bad to return a local variable by address. Is there any specific reason for wanting this behavior?
You can new/malloc a char array or int, and then return it back. You are guaranteed to have the variable in scope, as long as you do not manually free/delete the memory. Then you can happily access the memory from other functions.
Hope this helps.
your first function is not valid, you should return
const char*
and yes, you can return adresses of static variables: they are not destroyed when function returns because they are alocalted in static data memory segment
Related
I want to return an array of chars and this is the code
char convert(string user){
int n = user.length();
char char_array[n+1];
strcpy(char_array,user.c_str()) ;
return char_array;
}
You cannot return an array from a function. You can return a pointer to the first element of such array. Good news is: That function already exists. It is the std::string::c_str method.
void foo(const char*); // <- legacy, cannot modify, must pass c-string
std::string x{"Hello World"};
foo( x.c_str() );
In your code, this char char_array[n+1]; is not valid standard C++. See here for details:
Why aren't variable-length arrays part of the C++ standard?
Moreover you attempt to return a pointer to a local array. Once the function ends the arrays lifetime has passed and the pointer is of no use. More on that here:
Can a local variable's memory be accessed outside its scope?
Last (and least) you declared the function to return a char when you wanted a char*. However, fixing that won't really help due to the last point.
This question already has an answer here:
How long does a string constant live in c++?
(1 answer)
Closed 5 years ago.
Normally, I would return a std::string from a function because returning a const char* would require the caller to provide an output memory buffer, and that buffer is not resizable.
But is returning a const char* valid if its from a string literal?
const char* generate_c_string() {
return "ABC";
}
Doing in this way (if valid) would likely be faster as I would not need to dynamically allocate memory to construct a std::string.
It probably is valid, because const char* x = "ABC"; is valid. Is there a reference from the C++ standard that substantiates its validity?
This is valid, for string literals,
String literals have static storage duration, and thus exist in memory for the life of the program.
The pointer returned would remain valid in the life of the program.
I know that "literals" (c strings, int or whatever) are stored somewhere (in a read only data section apparently .rodata) maybe this is not accurate...
I want to understand why this code causes a runtime error:
#include <iostream>
using namespace std;
const int& foo()
{
return 2;
}
const char* bar()
{
return "Hello !";
}
int main() {
cout << foo() << endl; // crash
cout << bar() << endl; // OK
return 0;
}
foo returns a const reference on a literal (2) why does this cause a crash ? is the integer 2 stored in the stack of foo() ?
See also : Why are string literals l-value while all other literals are r-value?
I see why this is confusing so I will try to break it down.
First case:
const int& foo()
{
return 2;
}
The return statement makes a temporary object which is a copy of the literal 2. So its address is either non-extant or different from the location of the literal 2 (assuming literal 2 has a location - not guaranteed).
It is that temporary whose reference is returned.
Second case:
const char* bar()
{
return "Hello !";
}
The return statement makes a temporary object which is a copy of a pointer to the address of the first element of the literal char array. That pointer contains the actual address of the literal array and that address is returned by copy to the caller.
So to sum up. The second one works because the return statement takes a copy of the literal's address and not a copy of the literal itself. It doesn't matter that the storage for the address is temporary because the address still points to the correct place after the temporary holding its value collapses.
That is indeed very confusing, and in order to understand what's happening, one has to dive very deep in the language specification.
But before we do this, let me remind you that compiler warnings are your friends. With a sufficient level of warnings, you should see following when compiling your example:
In function 'const int& foo()': 3 : warning: returning reference to
temporary [-Wreturn-local-addr] return 2; ^
Now, what is happening in your first example? One can not really take an address of the integral literal, since they do not really exist as objects. However, one is allowed to bind constant references to literals. How is it possible, when everybody knows that references are akin to pointers? The reason is that when you bind a const reference to the literal, you do not really bind it to the literal. Instead, compiler creates a temporary variable, and binds your reference to it. And that variable is an object, albeit short-lived one. Once you function returns, the temporary object is destroyed, and you end up with dangling reference -> crash.
In the second example, "hello" is a literal, but you are not returning the literal - you are returning a pointer to the string. And a pointer remains valid, because the string it points to remains valid.
This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 7 years ago.
EDIT: The question about why the code in this question works has been answered by the linked question in the duplicate marking. The question about string literal lifetime is answered in the answer to this question.
I am trying to understand how and when the string pointed to by const char * gets deallocated.
Consider:
const char **p = nullptr;
{
const char *t = "test";
p = &t;
}
cout << *p;
After leaving the inner scope I would expect p to be a dangling pointer to const char *. However in my tests it is not. That would imply that the value of t actually continues to be valid and accessible even after t gets out of scope.
It could be due to prolonging the lifetime of the temporary by binding it to const reference. But I do no such thing and even by saving the reference to t in a member variable and printing the value from different function later still gives me its correct value.
class CStringTest
{
public:
void test1()
{
const char *t = "test";
m_P = &t;
test2();
}
void test2()
{
cout << *m_P;
}
private:
const char **m_P = nullptr;
};
So what is the lifetime of the t's value here? I would say I am invoking undefined behaviour by dereferencing a pointer to a value of a variable that went out of scope. But it works every time so I think that is not the case.
When trying some other type like QString:
QString *p = nullptr;
{
QString str = "test";
p = &str;
}
cout << *p;
the code always prints the value correctly too even though it should not. str went out of scope with its value and I have not prolonged its lifetime by binding it to const reference either.
Interestingly the class example with QString behaves as I would expect and test2() prints gibberish because the value indeed went out of scope and m_P became dangling pointer.
So what is the actual lifetime of const char *'s value?
The variables p and t are stack variables that you declared, so they have a lifetime that ends at the end of their enclosing block.
But the value of t is the address of the string literal "test", and that is not a variable you declared, it's not on the stack. It's a string literal, which is a constant defined in the program (similar to the integer literal 99 or the floating point literal 0.99). Literals don't go out of scope as you expect, because they are not created or destroyed, they just are.
The standard says:
Evaluating a string-literal results in a string literal object with static storage duration, initialized from the given characters as specified above.
So the object that the compiler creates to represent the literal "test" has static storage duration, which is the same duration as globals and static variables, meaning it doesn't go out of scope like a stack variable.
The value of p is the address of t, which does become an invalid pointer when t goes out of scope, but that doesn't mean that the value stored at that address suddenly becomes inaccessible or gets wiped. The expression *p is undefined behaviour, but it appears to work because nothing has reused that memory location yet so *p still contains the address of the string literal. For more details on that see the top answer to Can a local variable's memory be accessed outside its scope?
Compilers put literal strings into a statically allocated space which is loaded into a protected segment of the virtual memory, such that those strings can be shared over the entire lifetime of the process (the value is a constant, so no need to take the overhead of constantly springing them into existence). Looking for something like that to be deallocated is a waste of time, since it never actually happens.
The variables are stack-allocated. The string constant should be thought of as just that: a string constant...like the number 3.
String literals get allocated in the static storage.
If you mention a string literal anywhere in your program, it's as if you did:
static const char someUniqueIdentifier[]="the data";
in the global scope.
const char* str = "some string"; means make sure "some string" exists as a constant null-terminated array in the static section of the program and point str to it.
You're however referencing your automatic (=on the stack) pointer in the first example, not the static storage string. That indeed has a lifetime limited to it's scope, however when you invoke test2(), the scope of test1() hasn't ended yet.
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Difference between pointer variable and reference variable in C++
This is a continuation of this question
Is a reference variable just another name of const pointer variable? If they are different what is the difference between a variable declared as a reference variable and a variable declared as a const pointer variable?
Just for fun:) A reference can not be NULL but a const pointer can be.
OK. The problem is that there is no such thing like reference variable. Reference is not a variable at all. It is not an object. It actually has no size at all. It is just alternative name of the original object.
Check this:
struct A
{
int i[5];
};
int main()
{
std::cout << (sizeof(A&) == sizeof(A)) << std::endl;
std::cout << (typeid(A&) == typeid(A)) << std::endl;
return 0;
}
A& has the same size as A
A& has the same type as A
Is a reference variable just another name of const pointer variable?
No.
If they are different what is the difference between a variable declared as a reference variable and a variable declared as a const pointer variable?
They are completely different things, and there is not enough room to explain everything you need to know here. Read this. Actually, read the entire FAQ. You'll learn a lot.