It looks like passing std::strings by reference to const (as done in ParseHashStr() in core_io.h) would be much better than passing string literals (for which by-value or by-reference-to-const doesn't matter, as you rightly point out).
<details><summary>test</summary><p>
// string-passing.cpp
//
// $ clang++ -std=c++17 string-passing.cpp && ./a.out
// foo(string) took 436096 cycles
// bar(string) took 156324 cycles
// foo("string literal") took 1464669 cycles
// bar("string literal") took 1463397 cycles
#include <ctime>
#include <iostream>
#include <string>
void foo(std::string s) { return; }
void bar(const std::string& s) { return; }
int main() {
std::string s = "blockhash";
auto start = clock();
for (int it = 0; it < 100000000; ++it) {
foo(s);
}
std::cout << "foo(string) took " << (clock() - start) << " cycles" << std::endl;
start = clock();
for (int it = 0; it < 100000000; ++it) {
bar(s);
}
std::cout << "bar(string) took " << (clock() - start) << " cycles" << std::endl;
start = clock();
for (int it = 0; it < 100000000; ++it) {
foo("blockhash");
}
std::cout << "foo(\"string literal\") took " << (clock() - start) << " cycles" << std::endl;
start = clock();
for (int it = 0; it < 100000000; ++it) {
bar("blockhash");
}
std::cout << "bar(\"string literal\") took " << (clock() - start) << " cycles" << std::endl;
return 0;
}
</p></details>
Replacing the blockhash, hash, and txid string literals by a constant would do it (and the parameter 1 ones look like they should be txid as well).