1

I want to find the most efficient way to concatenate multiple strings of type std::string.

One of the issues is that I also have a char within it, and another issue is that I need it to be as fast as possible. Let's say I have the following variables defined:

std::string defaultName = "default"; 
std::string paramFullName = "Elasticity";

First try:

std::string paramName = defaultName + "_" + paramFullName[0] + "_";

This code does not compile with Intel C++14 compiler.

Second try:

std:string paramName;
paramName += defaultName + "_";
paramName += paramFullName[0];
paramName += "_";

This time the output came as expected:

"default_E_"

I still wanted to test another way:

Third try:

std:string paramName;
paramName.append(defaultName + "_");
paramName.append(1, paramFullName[0]);
paramName.append("_");

Output was OK again, because of the separation of the char from the strings.

"default_E_"

When testing for timing, I've found out that the append option is faster that the +=.

I want to know if there is a better, more efficient way,
and also could I minimize the number of lines so it wouldn't look so ugly?

15
  • First way works fine. Did you rememeber to #include <string> and also spell defaulName correctly and/or remember the ; at the end of std::string paramFullName = "Elasticity"? Commented Jul 5, 2022 at 10:24
  • 2
    I would create a result string with the required length and write into it to avoid unnecessary memory allocations. append and other concatenation methods could require more memory and allocate new memory in each step. Commented Jul 5, 2022 at 10:25
  • defaulName + "_" + paramFullName[0] + "_" should be parsed as ((defaulName + "_") + paramFullName[0]) + "_". I.e. all "additions" should be between either a std::string and a const char*, or between a std::string and a char, which both should work fine. Commented Jul 5, 2022 at 10:25
  • 1
    @BuildSucceeded It's long since I did last performance comparisons, but the last time std::stringstream was much slower than anything else. Commented Jul 5, 2022 at 10:44
  • 5
    Consider github.com/fmtlib/fmt Commented Jul 13, 2022 at 9:05

2 Answers 2

5

The fastest way is most likely going to involve allocating a destination string once, which means you will need to know the size of all your input strings. Luckily std::string, string literals and individual characters have a O(1) size, so only c style strings need to be looped twice.

namespace string_builder
{
    std::size_t length(char str)
    {
        return 1;
    };
    
    void append(std::string & dest, char str)
    {
        dest.push_back(str);
    }
    
    std::size_t length(const char * str)
    {
        return std::strlen(str);
    };
    
    void append(std::string & dest, const char * str)
    {
        dest.append(str);
    }
    
    template<std::size_t N>
    std::size_t length(const char (&str)[N])
    {
        return N;
    }
    
    template<std::size_t N>
    void append(std::string & dest, const char (&str)[N])
    {
        dest.append(str, N);
    }
    
    std::size_t length(const std::string & str)
    {
        return str.size();
    }
    
    void append(std::string & dest, const std::string & str)
    {
        dest.append(str);
    }
}

template<typename... Ts>
std::string concat(const Ts &... ts)
{
    std::string result;
    result.reserve((string_builder::length(ts) + ...));
    (string_builder::append(result, ts), ...);
    return result;
}

See it on coliru

Sign up to request clarification or add additional context in comments.

Comments

-1

Use the "built-in" C++ "stringbuilder" :

#include <iostream> // for std::cout
#include <sstream>  // for std::ostringstream
#include <string>   // for std::string

int main()
{
    std::ostringstream oss;
    std::string s("Two");
    oss << "One" << ' ' << s << ' ' << "Three";
    std::string result(oss.str()); // concat result
    std::cout << result; // Console Output: One Two Three
}

OR (more concise, not using result variable)

std::cout << oss.str();

Using ostringstream object you can also concatenate any type of variables, provided that all of them are "streamable" (standard stream or the type itself know how to serialize what you are sending after operator << ):

std::ostringstream oss;
int one = 1;
std::string s("Two");
oss << one << ' ' << s << ' ' << 3;
std::string result(oss.str()); // concat result
std::cout << result; // Output: 1 Two 3

1 Comment

I downvoted because the question asks for most efficient, and according to my experience stringstreams are slower than all other options.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.