2

Lets say I have a char* allocated from a custom memory pool and filled with necessary data. I use that char* in the assign method of std::string class and make sure move varient is called by using std::move.

void DoWork(char* my_pool_allocated_buffer) {
    std::string s;
    s.assign(std::move(my_pool_allocated_buffer));
    //do some work with s
}

I have two questions.

  1. At the end of the method, would the std::string destructor try to delete my_pool_allocated_buffer it aquired through assign? Documentation says it will only delete memory it allocated through its own allocator however.
  2. After method exit, the my_pool_allocated_buffer will be freed by its pool. Does the use of std::move has any affect on this? (assuming the pool does not care about the actual data the buffer holds).
user3612009
  • 655
  • 1
  • 6
  • 18

4 Answers4

5

At the end of the method, would the std::string destructor try to delete my_pool_allocated_buffer it aquired through assign?

No, because it didn't acquire the buffer. It copied the contents into its own managed buffer.

Does the use of std::move has any affect on this?

No, std::move has no effect here (apart from confusing readers of the code). If there were a overload of assign that accepted an rvalue reference to a pointer, then that would be chosen; but there's no such overload, so it makes no difference.

(As an aside, such an overload to take "ownership" of a raw pointer would be a very bad idea, since there's no way of knowing whether a raw pointer is intended to "own" its target, or just refer to it. You should usually use smart pointers to express ownership, along with a convention that raw pointer don't have ownership.)

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
  • Thanks all. Well my inital requirement was to avoid the copy. That is, I wanted the std::string to use the memory pointed to by the my_pool_allocated_buffer without further allocations. – user3612009 Jul 09 '14 at 14:04
  • @user3612009: Then you'll have to use something other than `std::string` (or possibly do some form of dark magic with a custom allocator, but that's likely to be a nightmare). It always manages its own memory allocation. – Mike Seymour Jul 09 '14 at 15:17
2

When you call assign on string, it will copy the data from the provided buffer into the string. It no longer has any connection to the source of the original data. When the string goes out of scope, its destructor cleans up the string automatically. Your original buffer is not affected by this.

I'm not an expert on the new moving stuff in C++11, but I get the feeling your use here is wrong. I think it will only move the char * pointer, which is the same as copying it. It won't have any effect on the original data.

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
Neil Kirk
  • 21,327
  • 9
  • 53
  • 91
  • It is not wrong, per se, as it is legal; however it is confusing because it has absolutely no effect whatsoever. – Matthieu M. Jul 09 '14 at 14:19
1

If you look at e.g. this std::basic_string constructor reference you will see that there is no constructor which takes a universal reference to a pointer. That means that the std::move call has no effect, and the normal "char-pointer" constructor is used which copies the string, leaving the original pointer and memory intact.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • @Deduplicator It's a name that kind of stuck because [Scott Meyers used it](http://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers), but it's the double-ampersand references, also known as [prvalue](http://en.cppreference.com/w/cpp/language/value_category). – Some programmer dude Jul 09 '14 at 14:01
  • 1
    I know what they are. But not all r-value references come from universal references as he defines the term, and these here are none. Specifically, his universal references are references where the reference collapsing rules must be applied. – Deduplicator Jul 09 '14 at 14:04
1

This is a common misconception about std::move: It does not move anything, it is nothing more than a cast to an Rvalue (if you want to read more about this, you can have a look at this question.

in your case, you still call the normal string::assign(char*) function. Having a look in a standard library reference, the value is copied.

6) Replaces the contents with those of null-terminated character string pointed to by s. > The length of the string is determined by the first null character.

So, the text will be copied, and there is no link between your char* and s

Community
  • 1
  • 1
MatthiasB
  • 1,759
  • 8
  • 18