2

I was working on one my projects, and while I was making the constructor for a class, I was setting some of my variables to a default value. I went to set an std::string to NULL, and it gave me an error. But when I define an std::string and set it to NULL on the same line, it works without any errors. I was wondering why

First Example

std::string text = NULL;

worked, and

Second Example

std::string text;
text = NULL;

didn't work. Now I know you shouldn't set a string to NULL, or 0, but I found this on accident.

Does the first example call a constructor that takes a char*, and thinking that 0 is a pointer to a char? I thought = called a constructor too, so I don't get why they wouldn't both work, unless std::string specifically overloads the = operator.

I am using Microsoft Visual Studio Express 2013

3
  • 1
    Aren't you getting run-time error, at line std::string text = NULL;? Commented Nov 14, 2015 at 7:45
  • @mnciitbhu nope, I am using Visual Studio 2013 Express. No errors at all. Commented Nov 14, 2015 at 7:52
  • @mnciitbhu so there's apparently some sort of discrepancy between the two Commented Nov 14, 2015 at 7:57

2 Answers 2

4

Value of NULL evaluates to 0.

Now, std::string text = NULL; will call constructor taking const char* and try to copy the data, but since NULL doesn't point to anything, an error will occur at run-time, I am getting (with gcc 5.2) :

terminate called after throwing an instance of 'std::logic_error'
  what():  basic_string::_M_construct null not valid

Since, there is no operator= defined for std::string and int(or size_t), text = NULL; will not compile.

Sign up to request clarification or add additional context in comments.

10 Comments

But doesn't the = call the size_t ctor again?
@GregM It calls the assignment operator. It's a bit confusing but using operator= in the context of initialization invokes an implicit constructor, while doing it post-initialization invokes an assignment operator.
It does, but where it gets hairy is implicit construction. For example, if you have implicit: Foo(int x), and no overloaded assignment operator for int, then trying to do: Foo f; f = 123; ... will actually call the parameterized constructor for Foo to implicitly construct it, and then the implicitly-generated assignment Foo& operator=(const Foo&);
@GregM: Basically, yes. Performance-wise, the compiler can do shortcuts as long as the semantics don't change (i.e. creating the "temporary" in-place, or -- since C++11 -- move-constructing it.) The idea is, since there is no way to assign an int to Foo, the compiler looks for alternatives, and finds that it's possible to assign a Foo to Foo and possible to construct a Foo from int, so that's what it does.
@GregM you can check if copy constructor is also used by deleting copy constructor, and checking if there are any errors. See ideone.com/nLke48
|
1

The reason the 2nd assignment

text = NULL;

is in the VC++ compiler error message. It says:

error C2593: 'operator =' is ambiguous could be 'std::basic_string<char,std::char_traits,std::allocator> &std::basic_string<char,std::char_traits,std::allocator>::operator =(const _Elem)' or 'std::basic_string<char,std::char_traits,std::allocator> &std::basic_string<char,std::char_traits,std::allocator>::operator =(const _Elem *const )'

Breaking it down a bit, that says:

error C2593: 'operator =' is ambiguous could be 'std::string &std::string::operator =(const char)' or 'std::string &std::string::operator =(const char *const )'

So it doesn't work is because the compiler isn't sure whether 0 is meant to be a char value, or const char*.

It will compile if you use single quotes around the 0 to turn it into a char value:

text = '\0'; // NULL or can use any other character

Or if you cast it to a pointer type

type = (const char*)NULL; // Crashes, but now we're sure what type 0 is meant to be

that would compile also. Keep in mind assigning the std::string to a NULL pointer will crash as it tries to copy characters from NULL.

2 Comments

Along those lines, the reason the 1st constructor works is because there is no constructor that takes a single char, but there is one that takes a const char*, so passing NULL to the constructor is not ambiguous (just undefined behavior).
Yes, the std::string fill constructor that accepts char also requires an int argument, for how many of that char to use (it is std::string(int, char)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.