1

I have a C-Libraray function returning a C-String

const char* myFuncC(struct myS *);

Now I write a class mapper:

class myC {
  private:
    struct myS * hdl
    ...
  public:
    const char* myFunc() {
      return myFuncC(hdl);
    }

  // want to have...
    const std::string& myFuncS() {
      return ??? myFuncC(hdl);
    }
}

Now I would like to return a: const std::string& and I don't want to copy the C-String pointer data

How I do this?

update

Is there a C++ Class who act like a const C++-String class and using a const C-String pointer as string source ?

I would call this class a C++-String-ExternalExternal mean … using a external source as storage… in my case a "const char *"

Andreas Otto
  • 151
  • 8
  • I update the example… right I want to have **const std:.string&** as return of the class method. – Andreas Otto Jun 14 '18 at 08:00
  • You are guessing. Don't. Get a [good C++ book](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). – Ron Jun 14 '18 at 08:01
  • Why a `const std::string&`? – StoryTeller - Unslander Monica Jun 14 '18 at 08:01
  • Why a reference? – Davide Spataro Jun 14 '18 at 08:02
  • I don't want to copy the entire string… so i have to return a pointer or a reference… my problem is… how do I create a **std:string** reference from a C-String? – Andreas Otto Jun 14 '18 at 08:03
  • @AndreasOtto It is unclear what you are asking. Your best bet at this point are the books mentioned above. – Ron Jun 14 '18 at 08:04
  • 1
    There's no magic that allows you to return a reference without an underlying object it will refer to. And if you wish to avoid dangling reference hell, don't do cargo cult programming with references. Prefer values to references as a default. – StoryTeller - Unslander Monica Jun 14 '18 at 08:05
  • @AndreasOtto you can't, std::string must allocate its own string. You can't get around that by trying to point a std::string& at a c string. – George Jun 14 '18 at 08:07
  • 1) I update the question: restriction!! → I **don't** want to copy the C-String pointer data 2) Why I need to buy and read a book for such a simple question ? – Andreas Otto Jun 14 '18 at 08:07
  • 1
    Because the very nature of your request shows a misunderstanding of some C++ fundamentals. It's not pointed out as a shortcoming of you personally, but to help you write better C++ in general, and to avoid such headaches in the future. – StoryTeller - Unslander Monica Jun 14 '18 at 08:10
  • I disagree with the comments here, this is a perfectly reasonable question, and a large part of the reason for `std::string_view`’s existence. Just because it’s not possible as OP stated doesn’t make it unreasonable. This question is succinct and answerable. – Konrad Rudolph Jun 14 '18 at 08:13
  • @AndreasOtto Because C++ is a strange and complex beast. While things might appear simple on the surface, the underlying complexity requires you to read the book. Then you get the _a-ha_ moment and the entire universe springs into existence. – Ron Jun 14 '18 at 08:13
  • I understand that this is a problem… that is the reason why I ask :-) if I want to write a Wrapper for an existing C-API ... and to be C++ conform I would like to operate 100% on C++-String… and I understand this is **not** possible without *expensive* copy "strings" around. Is this the final answer? – Andreas Otto Jun 14 '18 at 08:14
  • @AndreasOtto - If you are willing to dispense with `std::string` there are alternatives, yes. I suggest you add into your question a note about who manages the lifetime of the buffer you return. – StoryTeller - Unslander Monica Jun 14 '18 at 08:15
  • 1
    @AndreasOtto please don't be so stubborn. A `std::string` is a class, which has all kinds of extra features. Internally the string stores a null-terminated character array (as of C++11). But there is much more in there. You cannot simply interpret a C-style character array as a C++ `std::string`. – JHBonarius Jun 14 '18 at 08:19

2 Answers2

4

std::string, by definition, owns its memory and there’s nothing we can do to change this. Furthermore, by returning a reference you’re creating a dangling reference to a local variable (or a memory leak).

However, the idea of encapsulating contiguous character ranges in a string-like interface without copying is such a common problem that C++17 added a new type, std::string_view, to accomplish exactly that. With it, your code can be written as:

std::string_view myFuncS() {
    return {myFuncC(hdl)};
}

A string_view isn’t a string but it has a very similar API and the idea is to use it instead of many current uses of string const&. It’s perfect for the job here.

Note that we are returning a copy, to avoid a dangling reference. However, this does not copy the underlying memory, and is cheap — almost as cheap as returning the reference.

Konrad Rudolph
  • 482,603
  • 120
  • 884
  • 1,141
1

Simply return a new string:

std::string myFuncS() {
  return std::string(myFuncC(hdl));
}

If you really need a refence or a pointer then allocate the string on the heap and return a pointer to it:

std::unique_ptr<std::string> myFuncS() {
       return std::unique_ptr<std::string>(new std::string(myFuncC(hdl)));
}
Ron
  • 13,116
  • 3
  • 25
  • 45
Davide Spataro
  • 6,761
  • 1
  • 21
  • 36
  • 1. I have a underlying C-API function the C-String is my FIXED restriction. 2. in your example you still copy the C-String to the heap.. I don't want to copy the C-String data at all. – Andreas Otto Jun 14 '18 at 08:10
  • @AndreasOtto you need to have a copy of the `const char*` into the `string`. Take a look at `string_view` which is what you need (C++17 required) https://stackoverflow.com/questions/20803826/what-is-string-view – Davide Spataro Jun 14 '18 at 08:15