0

It's my understanding that copy-on-write for std::string is no longer present with C++11.

The following code would demonstrate that this isn't completely true.

#include <string>
#include <iostream>

void Modify(std::string& s)
{
    if (!s.empty())
    {
         *const_cast<char*>(s.data()) = 'W';
    }
}

int main()
{
    std::string a = "Hello World";
    std::string b = a;  // Does not do a deep copy.

    Modify(a);

    std::cout << (a == b ? "Failed\n" : "Succeeded\n");

    return 0;
}

I'm not sure what rule I'm breaking here. Whatever about casting const away, why isn't the deep copy done? I know it can be forced with std::string b = a.c_str(); but that's not the point.

g++ (Ubuntu 4.8.2-19ubuntu1) 4.8.2

Praetorian
  • 106,671
  • 19
  • 240
  • 328
James
  • 9,064
  • 3
  • 31
  • 49
  • 3
    gcc's `std::string` is still COW – Praetorian Sep 15 '14 at 17:38
  • by the way `msvc` implements `std::string` in a non standard way too, `libc++` is probably the only standard library with a relatively large popularity that implements `std::string` in the way that the standard requires . – user2485710 Sep 15 '14 at 17:42
  • In C++11 `std::string` is not allowed to be COW. – Tommy Andersen Sep 15 '14 at 17:44
  • Modifying string data through the result of `.data()` is UB, so that's one rule you're breaking here. – bames53 Sep 15 '14 at 17:44
  • 5
    @user2485710 What implementation feature of MSVC are you referring to?The only cleverness that I've heard is in MSVC's string is the small string optimization, which is a legal C++11 implementation. libc++ uses SSO too. – bames53 Sep 15 '14 at 17:47
  • @bames53 there is a talk where this is mentioned www.youtube.com/watch?v=BezbcQIuCsY#t=40m55s but there is another comment that points to something not being correctly implemented in the way `std::string` is being copied or moved, the comment dated `12 Jun 2014 7:11 PM` ( sorry no permalink from that page apparently ) here http://blogs.msdn.com/b/vcblog/archive/2014/06/11/c-11-14-feature-tables-for-visual-studio-14-ctp1.aspx?PageIndex=2 and there is still no clear answer to that question . – user2485710 Sep 15 '14 at 17:56
  • 3
    @user2485710 That comment is talking about a bug in the `std::vector` implementation where moving the `vector` fails to fallback to copying elements when the `value_type` doesn't have a `noexcept` move constructor, thereby not achieving a strong exception guarantee. SSO for `std::string` is still legal because `std::string::swap` is allowed to invalidate iterators/references unlike other containers. The only oddity of implementing SSO is that when it's active, moving an `std::string` will be `O(N)` (for small values of `N`). – Praetorian Sep 15 '14 at 18:09
  • @Praetorian I'm not really convinced by that since a container moves or copies elements, when you say *vector moves T*s, it's being implied that `T` is an element, if a `vector` has problems dealing with a move, problems of any kind, probably `T` is being involved too . It's also the fact that I can't see any major problem with `vector`s too, there is this weird thing that happens only when a `vector` meets a `string`, I would like to get an exhaustive explanation too anyway, at the moment the explanation sounds fuzzy to me . – user2485710 Sep 15 '14 at 18:15
  • @user2485710: Instead of comments about "weird things" happening, why don't you get clear about what case is affected and then write a nice question about (actual vs mandated vs implementation-specific) behavior concerning that case? – Ben Voigt Sep 15 '14 at 19:24

0 Answers0