Binding a pointer to a link

Refer to the code below. In this code, I save the const char* returned by test.c_str() to the link. My question is: will data refer to the contents of test correctly? I think the ptr returned by test.c_str() will be temporary, and if I bind it to a link, the link will be invalid.

Am I thinking right?

 class RefPtrTest { std::string test; StoringClass storingClass; public: RefPtrTest(): test("hello"), storingClass(test.c_str()) { } } 

where is the storingclass

 class StoringClass { const char*& data; public: StoringClass (const char*& input): data(input) { } } 

EDIT1: Let's just not look at what std :: string does. Suppose I use my own class called mystring

 class RefPtrTest { const mystring test; StoringClass storingClass; public: RefPtrTest(): test("hello"), storingClass(test.getInternalPointer()) { } } 

getInternalPointer returns an internal pointer. I want to test this hypothesis, and the storingClass(test.getInternalPointer()) ptr returned by test.getInternalPointer() will be temporary, and if I bind it to a link, that link will not be valid. Am I correct?

EDIT2: This StoringClass is not under my control. This is basically a template class where it stores a reference to a type. I use it for const char* . I know all the design issues that you raised. But I cannot change this class, and I have to use it for const char * . There is no other way.

+4
source share
6 answers

If a StoringClass needs a reference to a pointer, you must make sure that there is a pointer to which it refers (and modifies, since it is not a reference to a constant), with a lifespan until the link is specified.

 #include <string> #include <iostream> template <typename T> class StoringClass { T& data; public: StoringClass (T& input): data(input) { } void print() const { std::cout << data << "\n"; } void set(T x) { data = x; } }; class RefPtrTest { const std::string test; const char *ptr; StoringClass<const char*> storingClass; public: RefPtrTest(): test("hello"), ptr(test.c_str()), storingClass(ptr) { } void print() const { storingClass.print(); } void set(const char* x) { storingClass.set(x); } }; int main() { RefPtrTest t; t.print(); t.set("world"); t.print(); } 

Conclusion:

 hello world 

IMO StoringClass is a bit weird. For example, I could also mark the set const functions, and it will still work. But if you need to use it, you must use it. If you can use the StoringClass<const char *const> instead, this might be better: this ensures that you do not call any StoringClass functions that change the pointer. The way you asked a question suggests that you do not expect this to happen.

Edit:

If test not const, although RefPtrTest could have a function:

 void set_another_way(const char *x) { test = x; set(test.c_str()); } 

Which will change the line and update the pointer referenced by storingClass . The body of the function is equivalent to test = x; ptr = test.c_str(); test = x; ptr = test.c_str(); . Assuming a single-threaded code that also takes into account any doubts about the validity of the value of the pointer returned by test.c_str() , provided that set_another_way is the only means by which test ever changed.

Honestly, storingClass should not be called storingClass . He does not store anything; -p

+1
source

Yes, your thinking is correct ( test.c_str() returns temp, so you cannot use it to initialize a link) unless test.c_str() returns a link to a pointer that I don’t think it does ... is not it?

This should give you a compilation error, however, have you tried?

In this particular case, actually using a pointer for something does not make much sense. But if you are only asking about pointers to links, then you are right (regardless of type).

+3
source

The standard has the following: c_str (21.3.6 / 2)

Required: the program should not change any of the values ​​stored in the array. Also, the program will not consider the return value as a valid pointer after any subsequent call to a non-constant member function of the basic_string class, which designates the same object as this.

So, the answer is no, you cannot treat the pointer as a reference to the contents of the string (after calling any non-end function in the string).

+3
source

You should not modify the string buffer directly if this is what you are trying to do.

When dealing with pointers in general, you only need a link to a pointer if you want to change an address that has a pointer type. If you only want to change the buffer, you can just save the char *.

If you want to access a buffer like this, use std :: vector instead, something like this:

 std::vector<char> v; v.resize(size); strcpy(&v.front(), "testing"); 
+1
source

See the following comment about the member function std :: string c_str () from cplusplus.com :

The returned array indicates the internal location with the necessary space for this sequence of characters plus its terminating null character, but the values ​​in this array should not be changed in the program and are provided only if they remain unchanged until the next invocation of a mutable function is a member of a string object.

Although you are not calling any non-constant member functions in the code you posted, this is not a good idea. When you change the private test variable std :: sting in the RefPtrTest class, you inadvertently affect the StoringClass class (this violates the RefPtrTest encapsulation). Someone supporting your code later (maybe you) may not understand this and introduce an error / failure.

+1
source

This may be fair. However, you should not depend on this behavior.

The string class implementation has char* below, and the c_str() method most likely returns a pointer to the beginning of this array. However, since the string changes over time, this internal array can move in memory, resize, in general. You must call c_str() every time you want to convert string to char* .

It probably just returns a pointer to the internal memory, so it is very fast.

-1
source

Source: https://habr.com/ru/post/1305766/


All Articles