Does std::move on std::string garantee that .c_str() returns same result?
Asked Answered
P

4

7

I want to provide zero-copy, move based API. I want to move a string from thread A into thread B. Ideologically it seems that move shall be able to simply pass\move data from instance A into new instance B with minimal to none copy operations (mainly for addresses). So all data like data pointers will be simply copied no new instance (constructed via move). So does std::move on std::string garantee that .c_str() returns same result on instance before move and instance created via move constructor?

Privation answered 22/4, 2015 at 19:6 Comment(9)
std::move is just a cast. It doesn't do anything.Cannular
I'm not convinced that subsequent calls to .c_str() are guaranteed to return the same pointer even without the attempted move. It would be a weird thing for the standard to require that (even an implicit requirement) although I'd love a language lawyer to quote me the standard. (I know it would have to be a really weird implementation that did this though)Cupel
@MikeVine it can clearly not be expected to return the same pointer between changes. For example if the string size was increased arbitrarily. If nothing is said about it in the standard, then any non-const method is free to influence this.Bandler
@Johan Lundberg Its not even that. I could think of a string implementation (lets say one which stores the string twice, stupid I know but I think its standard compliant) that could return a different pointer from c_str() if called twice without modification. At least I think this is ok, but like I said I'd like to see something from the standard which disallows this. Purely for interest ofc.Cupel
Remember that const means thread safe, so unless such hypothetical implementation protects that whole thing it's not allowed.Bandler
consider using string::swap rather than move. It's much more likely to leave the data in the same place (but no, it is not guaranteed)Permatron
@JohanLundberg Alas, const does not always mean threadsafe. You'd have to look at the implementation of the class to be sure of that -- as one example "mutable" preserves logical, but not physical constness, and is definately not threadsafe.Permatron
C++ standard library classes and functions are thread safe in that they allow access to const methods without external synchronization. Const methods are allowed to mutate internal states (mutable or cast away const) only if it can be done by still preserving correct behavior (atomic or otherwise synchronized if it has to be), or as-if. herbsutter.com/2013/01/01/video-you-dont-know-const-and-mutableBandler
C++-strings usually have small-string-optimizations. If c_str would be the same for a moved string, small-string-optimizations wouldn't be possible because of the internal buffers of the string-objects have different adresses. So take it the opposite way: if the standard would mandate .c_str() to be the same across moved strings, small-string-optimizations wouldn't be possible.Heliozoan
B
3

No,

but if that is needed, an option is to put the string in std::unique_ptr. Personally I would typically not rely on the c_str() value for more than the local scope.

Example, on request:

#include <iostream>
#include <string>
#include <memory>

int main() {
    std::string ss("hello");
    auto u_str = std::make_unique<std::string>(ss);
    std::cout << u_str->c_str() <<std::endl;
    std::cout << *u_str <<std::endl;
    return 0;
}

if you don't have make_unique (new in C++14).

auto u_str = std::unique_ptr<std::string>(new std::string(ss));

Or just copy the whole implementation from the proposal by S.T.L.:

Ideone example on how to do that

Bandler answered 22/4, 2015 at 19:24 Comment(1)
How to put a string into unique_ptr.having it by value?Privation
C
13

No. There's no requirement for std::string to use dynamic allocation or to do anything specific with such an allocation if it has one. In fact, modern implementations usually put short strings into the string object itself and don't allocate anything; then moving is the same as copying.

It's important to keep in mind that std::string is not a container, even though it looks very similar to one. Containers make stronger guarantees with respect to their elements than std::string does.

Cannular answered 22/4, 2015 at 19:9 Comment(2)
So in case of for example std::vector we are garanteed to have pointer to the first oiunt to the same place after move?Privation
@DuckQueen: I'm not really sure. The standard says that the target container after move has the same value as the operand before the move, but that's a bit vague. Only for swap does it say that no container elements are touched.Cannular
D
8

No, it's not guaranteed.

Guaranteeing it would basically prohibit (for one example) the short string optimization, in which the entire body of a short string is stored in the string object itself, rather than being allocated separately on the heap.

At least for now, I think SSO is regarded as important enough that the committee would be extremely reluctant to prohibit it (but that could change--when the original C++98 standard was written, they went to considerable trouble to allow copy-on-write strings, but they are now prohibited).

Doublecross answered 22/4, 2015 at 19:11 Comment(0)
B
3

No,

but if that is needed, an option is to put the string in std::unique_ptr. Personally I would typically not rely on the c_str() value for more than the local scope.

Example, on request:

#include <iostream>
#include <string>
#include <memory>

int main() {
    std::string ss("hello");
    auto u_str = std::make_unique<std::string>(ss);
    std::cout << u_str->c_str() <<std::endl;
    std::cout << *u_str <<std::endl;
    return 0;
}

if you don't have make_unique (new in C++14).

auto u_str = std::unique_ptr<std::string>(new std::string(ss));

Or just copy the whole implementation from the proposal by S.T.L.:

Ideone example on how to do that

Bandler answered 22/4, 2015 at 19:24 Comment(1)
How to put a string into unique_ptr.having it by value?Privation
K
1

It is documented here, so you can assume that the c_str() result is stable under some conditions.

You cannot however assume that c_str() will remain the same after move. In practice it will stay in case of long string, but it won't stay for short strings.

Karyotin answered 21/10, 2022 at 9:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.