digitalmars.D.learn - properly passing strings to functions? (C++ vs D)
- zack (17/17) Jan 11 2021 A beginner question: How to pass strings properly to functions in
- rikki cattermole (6/23) Jan 11 2021 If you are modifying text the reference and want the caller to see the
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (4/13) Jan 11 2021 C++ strings are reference counted, I think, so it is more to
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (13/22) Jan 11 2021 I meant allocation... The following prints "1", so no allocation.
- zack (4/6) Jan 11 2021 Just tried on Windows with Visual Studio, it prints "0". So I
- =?UTF-8?Q?Ali_=c3=87ehreli?= (7/12) Jan 11 2021 s=20
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (3/6) Jan 11 2021 Ah, I guess I've never used std::string for anything that
- IGotD- (22/25) Jan 11 2021 In D strings are immutable so there will be no copying when
- Q. Schroll (5/10) Jan 12 2021 Did you consider `in`? It will do that in some time and do it now
- IGotD- (7/11) Jan 12 2021 Has the redesignation of "in" like in the preview been formally
- Q. Schroll (20/30) Jan 12 2021 In D, `string` is an abbreviation for the type immutable(char)[],
A beginner question: How to pass strings properly to functions in D? Is there any allocation going on if just use a function as "myPrint"? In C++ I have often seen calls where one just passes a reference/const reference to a string to avoid allocation. C++: void myPrintCPP(const std::string& input){ ... } D: void myPrint(string text){ ... } void myPrintRef(ref string text) { ... } So the question is does a function call like (ref string ...) (myPrintRef) make any sense in D to avoid additional allocations? A D-Style String could be seen as "const(char)[]"? So as it is a slice it already is a kind of reference to some data elsewhere? Which means calling a function like "myPrint" in D wouldn't cause any allocation. Is this correct? Thank's for your help.
Jan 11 2021
On 12/01/2021 3:12 AM, zack wrote:A beginner question: How to pass strings properly to functions in D? Is there any allocation going on if just use a function as "myPrint"? In C++ I have often seen calls where one just passes a reference/const reference to a string to avoid allocation. C++: void myPrintCPP(const std::string& input){ ... } D: void myPrint(string text){ ... } void myPrintRef(ref string text) { ... }If you are modifying text the reference and want the caller to see the change, use this.So the question is does a function call like (ref string ...) (myPrintRef) make any sense in D to avoid additional allocations?There are no allocations for this.A D-Style String could be seen as "const(char)[]"? So as it is a slice it already is a kind of reference to some data elsewhere? Which means calling a function like "myPrint" in D wouldn't cause any allocation. Is this correct?alias string = immutable(char)[]; https://github.com/dlang/druntime/blob/master/src/object.d
Jan 11 2021
On Monday, 11 January 2021 at 14:12:57 UTC, zack wrote:A beginner question: How to pass strings properly to functions in D? Is there any allocation going on if just use a function as "myPrint"? In C++ I have often seen calls where one just passes a reference/const reference to a string to avoid allocation.C++ strings are reference counted, I think, so it is more to avoid a reference count increment than to avoid a collection.A D-Style String could be seen as "const(char)[]"? So as it is a slice it already is a kind of reference to some data elsewhere? Which means calling a function like "myPrint" in D wouldn't cause any allocation. Is this correct?D strings are backed by GC so they are passed by reference too.
Jan 11 2021
On Monday, 11 January 2021 at 15:23:23 UTC, Ola Fosheim Grøstad wrote:On Monday, 11 January 2021 at 14:12:57 UTC, zack wrote:I meant allocation... The following prints "1", so no allocation. #include <iostream> #include <string> std::string a("hello world"); void f(std::string b){ std::cout << (b.data() == a.data()) << std::endl; } int main() { f(a); }A beginner question: How to pass strings properly to functions in D? Is there any allocation going on if just use a function as "myPrint"? In C++ I have often seen calls where one just passes a reference/const reference to a string to avoid allocation.C++ strings are reference counted, I think, so it is more to avoid a reference count increment than to avoid a collection.
Jan 11 2021
On Monday, 11 January 2021 at 15:25:58 UTC, Ola Fosheim Grøstad wrote:I meant allocation... The following prints "1", so no allocation.Just tried on Windows with Visual Studio, it prints "0". So I guess this is platform/compiler dependent.
Jan 11 2021
On 1/11/21 8:22 AM, zack wrote:On Monday, 11 January 2021 at 15:25:58 UTC, Ola Fosheim Gr=C3=B8stad wr=ote:s=20I meant allocation... The following prints "1", so no allocation.=20 Just tried on Windows with Visual Studio, it prints "0". So I guess thi=is platform/compiler dependent.Yes. Earlier C++ string implementations used reference counting, which=20 caused multi-threading complications; so, many implementations switched=20 to copying. Ali
Jan 11 2021
On Monday, 11 January 2021 at 16:40:53 UTC, Ali Çehreli wrote:Yes. Earlier C++ string implementations used reference counting, which caused multi-threading complications; so, many implementations switched to copying.Ah, I guess I've never used std::string for anything that requires speed. Turns out that cpp.sh is outdated.
Jan 11 2021
On Monday, 11 January 2021 at 14:12:57 UTC, zack wrote:D: void myPrint(string text){ ... } void myPrintRef(ref string text) { ... }In D strings are immutable so there will be no copying when passing as function parameters. Strings are essentially like slices when passing them. I usually use "const string text" because D has no implicit declaration of variables. So using "ref" will not create a variable. This is contrary to C++ where passing as "const std::string &text" has a performance benefit and also C++ creates a unnamed variable for you. ex. void myFunction1(const string text); void myFunction2(const ref string text); myFunction1("test"); myFunction2("test"); -------> error cannot create an implicit reference then you have to do like this string t = "text"; myFunction2(t); This will work but you have to do the extra step by declaring t. Annoying as you cannot write text literals directly in the function parameters, therefore I do not use "ref" and it doesn't have a big benefit in D either.
Jan 11 2021
On Monday, 11 January 2021 at 16:53:50 UTC, IGotD- wrote:I usually use "const string text" because D has no implicit declaration of variables. So using "ref" will not create a variable. This is contrary to C++ where passing as "const std::string &text" has a performance benefit and also C++ creates a unnamed variable for you.Did you consider `in`? It will do that in some time and do it now with -preview=in. If you're using `const`, in almost all cases, `in` will work, too, and be better (and shorter).
Jan 12 2021
On Tuesday, 12 January 2021 at 18:12:14 UTC, Q. Schroll wrote:Did you consider `in`? It will do that in some time and do it now with -preview=in. If you're using `const`, in almost all cases, `in` will work, too, and be better (and shorter).Has the redesignation of "in" like in the preview been formally accepted as a part of language? I know that it was suggested to make "in" the optimized parameter passing for const which I like. However, if I'm going to use it I need to know if this going to be accepted as I don't want go around and change all the parameters back again if it was not accepted.
Jan 12 2021
On Monday, 11 January 2021 at 14:12:57 UTC, zack wrote:A beginner question: How to pass strings properly to functions in D? Is there any allocation going on if just use a function as "myPrint"? In C++ I have often seen calls where one just passes a reference/const reference to a string to avoid allocation. C++: void myPrintCPP(const std::string& input){ ... } D: void myPrint(string text){ ... } void myPrintRef(ref string text) { ... }In D, `string` is an abbreviation for the type immutable(char)[], i.e. slice of immutable char. The slice type is a pointer+length pair, a (T*, size_t) tuple, it is very lightweight. Using `ref T[]` (that includes `ref string` aka `ref immutable(char)[]` is the way if you want reassignments or expanding/shrinking of the array to be visible to the caller. Since the cost of copying a pointer and a length is very low, I'd just use this: void myPrint(string text) { ... } It'll be probably what you want. Since you cannot write the immutable characters, if you don't intend to reassign, expand, or shrink the string locally, you can use `in string text`. You can basically only read `in` parameters for information. What `in` buys you is that the compiler will figure out the best way to pass the object. C++'s const T& will reference always, which is worse than a copy for small types. D's `in` will copy if the compiler thinks it's cheaper than referencing. Give https://dlang.org/changelog/2.094.0.html#preview-in a read, if you want details about `in`. Use it when it applies. It also documents intent.
Jan 12 2021