Strings are a special managed type in Delphi and should be handled correctly. When comparing a simple procedure with the parameters
procedure Foo(const S: string)which results in no extra code vs by value
procedure Foo(S: string)which results in the following assembly being generated:
push dword ptr fs:[eax]
So nearly always pass your strings as const or var.
Update: Allen has some good points which I neglected to mention and I'll bring up into the post from the comments so everyone can see it. "This is good advice for nearly all cases. However there are a few cases where you should pass a string "by value." If the function you're calling manipulates a global string variable and there is a chance that the same global string can be passed in as a parameter, there is a chance that the global string variable is deallocated which would indirectly render parameter invalid as well. The same thing can happen with any of the managed types such as interfaces, dynamic arrays or variants."
Update: Rob Kennedy has more good points which I also neglected to mention so I'm bringing them into the post from the comments. What's happening in that assembler code is a try-finally block generated by the compiler. It's there to ensure that the reference count of the string parameter gets reduced before the function returns.