string initializing as NULL in C++ - c++

string a=NULL;
it gives error. Why and how can I initialize string as NULL?
but when I write
string a="foo";
this it works fine.

Actually to get an empty std::string, you just write
std::string a;
std::string's default constructor will give you an empty string without further prompting.
As an aside, using NULL in C++ is generally discouraged, the recommendation would be to either use 0 (which NULL tends to be defined to anyway) or if you have a modern enough compiler, nullptr.

There is a difference between null and empty string (an empty string is still a valid string). If you want a "nullable" object (something that can hold at most one object of a certain type), you can use boost::optional:
boost::optional<std::string> str; // str is *nothing* (i.e. there is no string)
str = "Hello, world!"; // str is "Hello, world!"
str = ""; // str is "" (i.e. empty string)

Let's break down what you are in fact doing:
string a=NULL;
First you execute string a. This creates a new object on the stack, with default value (an empty string). Then you execute a=NULL, which calls the assignment function of the string class. But what is NULL? NULL in C++ is macro expanded into just 0. So you are attepting to assign an integer to a string variable, which of course is not possible.
string a="abc"
works, because you want to assign a char array, and the string class has the assignment operator method overloaded for char arrays, but not for integers. That's why NULL doesn't work and "abc" works.

Related

How can this constructor that has pointer as the parameter receive string?

This is a constructor that I found from the internet, but it didn't have enough descriptions so I couldn't understand how it's even possible for this constructor to have string as a parameter.
For instance, if I say MyString str1("hello world this "hello world" goes into the constructor, but I have no idea how this string can get into this const pointer parameter. Can anyone explain how this is possible?
MyString::MyString(const char* str) {
string_length = strlen(str);
string_content = new char[string_length];
for (int i = 0; i != string_length; i++) string_content[i] = str[i];
}
When you get a const char* you are getting what is called a C string, which is a pointer to an array of characters that ends with a special value '0/' which you dont have to type. All strings that you write as literals in the code are of this form.
Dont confuse C strings with the C++ class strings (that works with C strings underneath) since are different.
So what is happening is the constructor doesn't actually receive a string, it receives a pointer that points to something of type char (and what is a string if not a sequence of chars, and I mean the concept of string and not the string object in C++ itself).
When you do "MyString str1("hello world")" what is actually passed to the constructor is a pointer that points to the first char of the string, in this case the "h" char.

how to return std::string from a function in c++

I'm trying to return a string from a function that does some processing.
I've tried returning it as an rvalue reference and also as an lvalue reference. didn't work :(.
processing function:
std::string processingFunction()
{
std::string str = "";
//processing...
strftime(&str[0], MAX_LENGTH, DATE_FORMAT, tm_STRUCT_ADRRESS);
return str;
}
use of the function:
std::string temp = processingFunction();
if(temp.empty())
{
//stuff
}
When debugging (in VS 2019), I can see the value of temp in the Watch, but temp.empty() always returns 1. Even if I can see that the value is present.
here is a screenshot for tl;dr:
m_bucket_function is the processing function
You define a std::string object and set it to "" (the empty string).
You then use strftime() to copy, as a C-style string, a representation of some time to memory starting at &str[0].
The expression &str[0] (where str is a std::string) does give you access to the initial byte of the data managed by the str::string object -- but it doesn't allocate memory to hold the new value, and it doesn't update the std::string object's internal data (including the length of the string it represents). Your call to strftime() is likely to clobber unallocated memory (undefined behavior).
You need to use strftime() to copy data into a char array, and then copy that data into your str. std::string's assignment operator will then take care of updating the metadata and allocating memory as needed.
There's no problem with returning a std::string by value, as you're doing.
temp.empty() always returns 1
just means the string is empty.
Now that you've posted more code and as #SkyZip comments, the problem lies in:
strftime(&str[0], ...
this gets strftime to overwrite memory by passing it the address of your string.
If you really have to use strftime you can do it like so:
std::string processingFunction()
{
char buff[MAX_LENGTH];
strftime(buff, MAX_LENGTH, DATE_FORMAT, tm_STRUCT_ADRRESS);
//processing...
return std::string(buff);
}
And as #Keith said, you are working with objects here. Not just plain old C data types.
Edit:
Just for reference, here is a similar question:
Current date and time as string

Assignment in strings

I'm having trouble understanding some particular behaviour of assignment in strings.
//method 1
std::string s;
s+='a' //This works perfectly
but
//method2
std::string s;
s="" + 'a';//This gives unexpected value
Why 2nd method gives unexpected value ? From what I've read string default constructor initialise string variable as empty string, if no constructor is specified. And s+='a' should be same as s=s+a. So why isn't the method 2 same as method 1?
And one more query on the same topic , if we can't initialise a string with char literal then how can we assign a char literal to it?
std::string s2='a'//gives error while compiling
whereas
std::string s2;
s2='a'//works perfect
From what I understand is we cannot initialise a string variable by char variable because string constructor needs argument of the type(const char *). Why is there not any such restriction while assigning?
For your first query ,
method 1 works perfectly cause in this method you are adding string object type and char literal .
and s+='a' , is indeed same as s=s+'a'
focus on the fact that s is string object type rather than string literal.
In the 2nd method , you are adding string literal
and char literal . Focus on the difference between the two , In first method there is string object you can add string or char literals to string object type,its one of the features provided by string object type . But you cant add simply add the literals with each other.In c++ , however "StringLiteral1" "StringLiteral2" , will result in the concatenation of the two string literals.
for 2nd query,
Initialisation is not the same as assignment , string object default constructor takes const char * to initialise . Assignment is a completely differenet story(if not,someone please do correct me ).
"" is a string literal of type const char[], and you are adding the string literal, i.e. the pointer to the first element, '\0', to another character. This will naturally give you something else then you expected.
If you want it to be the same as s += 'a', you'll need to use a std::string literal: s += ""s + 'a';. This works, as ""s is an empty std::string, and you just add another character to it.
When you write s="" + 'a'; Remember that "" is not a std::string but a const char*. And const char* doesn't have a predefined concatenation operator. That's why you are having an unexpected behavior instead of concatenation.

Using strings as arrays in C++

Our instructor told us that a string is the array of characters, and I was wondering whenever we use any array statically, we have to define its size before compiling the pro-gramme in C++ then why don't we do same with the string?
Thanks in advance.
The compiler can choose an array's size automatically to match its initial content, for example:
int a[] = { 3, 5, 2 };
So this is not something that string literals have and other arrays don't.
The string is an object, which is smarter than a character array. A character array is just an allocation in memory, it has no logic associated with it. However the string (because it is an object) is able to manage its own memory and expand as needed.
In C++ you can overload operators. Because the string class has its [ ] operators overloaded you can use the string as an array and access individual characters. However when you use the [ ] operators you are actually invoking a method on the string (namely operator[ ]).
So you can create a string, expand by adding to it, and access individual characters in it:
string str1 = "Hello "; // create a string and assign value
string str2("World"); // use the constructor to assign a value
str1 += str2; // append one string to another
cout << str1[0]; // should print H
But even though the opeartor overloading give it has the same feel as an array, it's actually an object.
if we talk about char* arr = "hello world";
now here "hello world" is given memory through a string object and the object is initialized by the constructor of the String class.
if we say String str = "hello world";
here again constructor of String class is called and it initializes the str object of String to point to the starting address of "hello world" which is stored somewhere in memory.
here we do not have to give the size, instead of that constructor of string class is doing all the trick of allocating dynamic memory and initializing.

String made from the first char of another string - why is it also printing the full original string?

Learning C++. I just want to grab the first character in a string, then make a new string based on such character, and then print it out:
#include <iostream>
using namespace std;
int main(int argc, const char * argv[]) {
string name = "Jerry";
char firstCharacter = name.at(0);
string stringOfFirstCharacter = string(&firstCharacter);
cout << stringOfFirstCharacter;
return 0;
}
The output is:
J
Jerry
I don't really know why is it also printing Jerry. Why is that?
Your code has undefined behavior. The signature of the constructor that takes a pointer to char requires that it is a pointer to a null terminated string, which it is not in your case since it is a single character.
My guess is that the implementation you have uses the small object optimization, and that "Jerry" is small enough that it is stored inside the std::string object rather than dynamically allocated. The layout of the two objects in the stack happens to be first firstCharacter, then name. When you call std::string(&firstCharacter) it reads until it hits the first null character (inside the std::string buffer) and stops there.
You are constructing an std::string object from a char* (because you are taking the address of firstCharacter). A pointer to a character is not interpreted as a character itself by the constructor of std::string, but rather as a null-terminated string.
In this case, your program has Undefined Behavior, because the address of firstCharacter is not the address of the first character of a null-terminated string.
What you should be doing is:
string stringOfFirstCharacter(1, firstCharacter);
cout << stringOfFirstCharacter;
If you really want to create a one-character string. However, notice that in order to print the character to the standard output, you could have simply written:
cout << firstCharacter;
Or even:
cout << name.at(0);
With string(&firstCharacter), you are using the std::string constructor of the form
std::string( const char* s, const Allocator& alloc = Allocator() );
That form expects a pointer to a null-terminated array of characters. It is incorrect to pass a pointer to character(s) that are not null-terminated.
With your intention of initializing the string with 1 char, you should use the form:
string( 1, firstCharacter )
The string constructor you're using (the one that takes a char * argument), is intended to convert a C-style string into a C++ string object - not a single character. By passing it a single character you cause undefined behaviour.
In your specific case, there appears to not be a zero byte in memory after firstCharacter, so the constructor runs through and includes all of name along with it!