4

Assume that I have a function that gets const string& as its input for example:

void foo(const string& s);

And then I have an internal buffer const char* buffer; which I know the size of it.

I think if I create string inline, still one copy would happen:

foo(string(buffer, n));

But there is no need to copy the buffer because all things are constant and I just need the functionality of string class not the buffer that it creates.

I must mention that I am not sure that copy happens or not, But looking at the constructor of string all of them said that copy would happen. I don't know compiler optimization can understand such situations or not and I could not find a way to sure that copy happened or not.

Is there any way to use an external buffer for string, or at least a way to sure that copy happens or not. I am using std string and c++11 currently.

TemplateRex
  • 69,038
  • 19
  • 164
  • 304
motam
  • 677
  • 1
  • 6
  • 24
  • 3
    `std::string` will **always** copy the contents into its own storage. Whether that needs to allocate any heap memory or not is unspecified, but it must copy. Are you concerned about allocation, or just the actual "copy" done by something like `strcpy` or memcpy`? – Jonathan Wakely Sep 21 '15 at 19:29
  • 1
    Similar question: http://stackoverflow.com/questions/361500/initializing-stdstring-from-char-without-copy – Soren Sep 21 '15 at 19:29
  • @JonathanWakely both of them are my concerns. Although allocation is more time consuming but copy time is also important in my program. Also, I think the similar question mentioned is concerned about just allocation not copy, reserving a huge buffer reduce the allocation time but not copy. But both of them seem unnecessary in this situation. – motam Sep 21 '15 at 19:43
  • In my project because my input is a buffer of data and I have not any control of it I cannot do this. So I must configure other functions that I have written before. – motam Sep 21 '15 at 19:50
  • I created a `string_view` class to do this. – Lightness Races in Orbit Sep 21 '15 at 20:04
  • Where can I find it? – motam Sep 21 '15 at 20:09
  • @HelloWorld I checked vstring but I could not find such a functionality in it also [this question](http://stackoverflow.com/questions/10463851/what-is-gccs-vstring) said that this is a base class for string and is not stable. – motam Sep 21 '15 at 20:11

2 Answers2

7

Yes, copying is always happening. BTW, you don't need to wrap std::string(buffer) as the constructor std::string(char const*) is implicit and a simple

foo(buffer);

will implicitly copy the buffer into the string. If you are the author of foo you can add an overload

void foo(char const*)

that avoids the copying. However, C strings are suffering from the problem that the null terminator is part of the string APIs, and so you can't easily create substrings without mutating the underlying string (a la strtok).

The Library Fundamentals Technical Specification contains a string_view class that will eliminate the copying like char const*, but preserves the subset capability of std::string

#include <iostream>
#include <experimental/string_view>

void foo(std::experimental::string_view v) { std::cout << v.substr(2,8) << '\n'; }

int main()
{
    char const* buffer = "war and peace";
    foo(buffer);
}

Live Example (requires libstdc++ 4.9 or higher in C++14 mode).

TemplateRex
  • 69,038
  • 19
  • 164
  • 304
  • Learning something new every day here. +1 – vsoftco Sep 21 '15 at 20:58
  • @vsoftco I think Scott Meyers at one point had a tentative Item "keep abreast of standardization developments" in the draft outline of his new Effective Modern C++ book (it didn't make it in the end). It's hard to keep up nowadays :) – TemplateRex Sep 21 '15 at 21:09
3

No, std::string manages its buffers. You can not have a string using an external buffer. On your sample at the moment you do string(buffer, n) it does NOT means your string instance will own your buffer and use it as string, but, instead, it will just copy the content of buffer to its internal buffers.

Wagner Patriota
  • 5,494
  • 26
  • 49