How to convert char* to const char* in C++? Why program 1 is working but program 2 can't?
Prog 1 (working):
char *s = "test string";
const char *tmp = s;
printMe(tmp);
void printMe(const char *&buf) {
printf("Given Str = %s", buf);
}
Prog 2 (not working)
char *s = "test string";
printMe((const char *)s); // typecasting not working
void printMe(const char *&buf) {
printf("Given Str = %s", buf);
}
The error I receive:
x.cpp:10:15: warning: conversion from string literal to 'char *' is
deprecated [-Wc++11-compat-deprecated-writable-strings]
char *s = "test string";
^
x.cpp:12:5: error: no matching function for call to 'printMe'
printMe(s);
^~~~~~~
x.cpp:6:6: note: candidate function not viable: no known conversion
from 'char *' to 'const char *&' for 1st argument
void printMe(const char *&buf)
^
1 warning and 1 error generated.
Thanks.
printMe takes an lvalue reference to a mutable pointer to const char.
In your first example, tmp is an lvalue of type mutable pointer to const char, so a reference can be bound to it without issue.
In your second example, (const char*)s creates a temporary const char* object. Lvalue references to mutable objects can't bind to temporaries, so you get an error. If you change printMe to take a const char* const& then the call will succeed with or without the explicit cast.
void printMe(const char * const& buf) {
printf("Given Str = %s", buf);
}
int main() {
char s[] = "test string";
printMe(s);
}
Live on Coliru
Of course, if you don't want to alter the object (the pointer) passed into printMe, then there's no reason to use a reference at all. Just make it take a const char*:
void printMe(const char * buf) {
printf("Given Str = %s", buf);
}
int main() {
char s[] = "test string";
printMe(s);
}
Live on Coliru
In the end, this is the same reason something like this:
void doSomething(const std::string& s) {}
int main() {
doSomething("asdf");
}
works while this:
void doSomething(std::string& s) {}
int main() {
doSomething("asdf");
}
does not. A temporary object is created, and the reference to non-const object can't bind to the temporary.
Related
I am learning C++. I am trying to pass a string to a function via const char* str. I understand the basic meaning of this passing.
In the function body, when I try char * ptrStr = str, I got error: cannot initialize a variable of type 'char *' with an lvalue of type 'const char *'. But when I try auto ptrStr = str, it works.
I have two questions here: (1) could you please help explain why the former fails while the latter works? (2) how to use smart pointers here?
#include<iostream>
#include<memory>
void func(const char* str){
char* ptrStr = str;
}
/*
void func(const char* str){
auto ptrStr = str;
}
*/
int main(){
func("5486321 ");
return 0;
}
The following code compiles and works. Why doesn't it produce an error: "cannot convert from 'const std::string' to 'std::string &'"?
class Test {
private:
std::string& _str;
public:
Test(std::string& str) : _str(str)
{ }
void SetStr(const std::string& str)
{
// std::string& s = str; // error: cannot convert from 'const std::string' to 'std::string &'
_str = str; // strange, but it works!
_str.append(", world!"); // it works too
}
const std::string& GetStr()
{
return _str;
}
};
...
std::string str = "";
Test test(str);
test.SetStr("Hello");
std::cout << test.GetStr(); // prints "Hello, world!"
std::cout << str; // also prints "Hello, world!"
You're confusing initialization and assignment.
_str = str; is an assignment, std::string::operator=(const std::string&) will be called, str is fine as the argument. That means the value of the object _str being bound to will be changed, not the reference itself. For the same reason _str.append(", world!"); is fine too.
While std::string& s = str; is a reference initialization, it fails because can't bind a const to non-const reference.
Once a reference have been initialized, it always references that object it has been initialized with, you can't reassign a reference variable.
When you do the assignment _str = str in the SetStr function, you don't change the reference, you change the object it references, which is not a constant object.
Simple example:
std::string string1 = "foo";
std::string const string2 = "bar";
std::string& string_ref = string1; // string_ref now is a reference of string1
string_ref = string2; // Doesn't change what string_ref references,
// instead changes string1
std::cout << string1 << '\n'; // Will output "bar"
Why can't I take a reference to s2 in foo? I'm compiling with gcc 5.1.0:
#include <cstring>
void foo(const char*& p)
{
while (*p && *p <= '5')
++p;
}
int main()
{
const char *s1 = "1234567890";
char *s2 = new char[strlen(s1) + 1];
strcpy(s2, s1);
foo(s1); // OK
foo(s2); // error
return 0;
}
I compiled with:
$ g++ test_reference.cpp
The compiler gave me:
test_reference.cpp: In function ‘int main()’:
test_reference.cpp:16:11: error: invalid initialization of non-const reference of type ‘const char*&’ from an rvalue of type ‘const char*’
foo(s2); // error
^
test_reference.cpp:3:6: note: initializing argument 1 of ‘void foo(const char*&)’
void foo(const char*& p)
^
For simplicity, you are trying to do:
char* s = ...;
const char*& r = s;
The const here may be misleading. You would think this is equivalent to:
int i = 4;
const int& ri = i;
Which works. But these are not equivalent. ri here is a reference to a const type, but r is a reference to a pointer to const char, that is not a const type.
The ultimate issue is that char* and char const* are not reference-related (meaning that the types are either the same or in the same hierarchy). However, if your reference was a reference to a const type, it would work fine. That is:
const char* const& cr = s;
Basically, you can take an lvalue reference to a non-const type T only from a reference-related type or from a class that is convertible to a reference related type. But you can take an lvalue reference to a const type from a much wider source of expressions:
double d = 4.0;
int& ri = d; // error: int, double aren't reference-related
const int& rci = d; // OK
You can cast it to const reference.
foo((const char *&) s2);
This question already has answers here:
How to convert a std::string to const char* or char*
(11 answers)
std::string to char*
(18 answers)
Closed 9 years ago.
I need to pass string into socket send() function which accepts char * only. So here I am trying to convert it:
void myFunc(std::string str) //Taking string here const is good idea? I saw it on some examples on web
{
char *buf = str.c_str; //taking buf const is good idea?
std::cout << str;
}
int main()
{
const std::string str = "hello world";
myFunc(str);
return 0;
}
Gives error:
test.cpp:6:18: error: cannot convert ‘std::basic_string<_CharT, _Traits, _Alloc>::c_str<char, std::char_traits<char>, std::allocator<char> >’ from type ‘const char* (std::basic_string<char>::)()const’ to type ‘char*’
First off, c_str() is a function so you need to call it.
Second, it returns a const char* not a char*.
All in all:
const char* buf = str.c_str();
First of all, Call c_str() has a function.
After it, c_str() return a const char*, you need to copy it if you want to have a char* using std::strcpy() : http://en.cppreference.com/w/cpp/string/byte/strcpy
Try:
void myFunc(std::string str)
{
const char *buf = str.c_str();
std::cout << str;
}
I have a funciton like
void foo(const char *&str)
{
cout<<str<<endl;
}
used like:
void main()
{
foo("hello");
char *h = "hello"
foo(h);
}
but both got an error
"can't convert from const char[] to const char *&"
if I change foo to void foo(const char *), there is no error can't I use const char *& as parameter
You got an error because the conversion is illegal. The reason
it is illegal is simple: it breaks const without requiring
a const_cast.
As an example of why it is forbidden, imagine that foo was:
void
foo( char const*& str )
{
str = "abc";
}
int
main()
{
char* h;
foo( h );
*h = '1';
}
If you're not going to modify str in foo, pass by value.
Pass by reference will works if you have char const* const&,
but there's no reason to use it here. It works because the
additional const means that you can bind a temporary to it (as
in the case of foo( "hello" ), where the argument is
a temporary resulting from the conversion of char const[6] to
char const*, and foo( h ) works, because the implicit const
conversions will work (in C++, but not in C!), as long as you
add const everywhere (and not just at one level).
Also, your code also uses a deprecated conversion to initialize
h. You should get a warning here. And void main is an
error, and shouldn't compile.
Edit:
Just to be clear, there's no problem with:
void f( char const*& str );
But you can only call it with an lvalue of type char const*;
anything else will either result in an illegal implicit const
conversion, or try to initialize a non-const reference with an
rvalue, which is illegal.
This will work
int main()
{
const char *h = "hello";
foo(h);
}