Efficiency of passing a combined string as an argument - c++

I want to call a function with an argument, which is a constructed string. For example:
std::string str = "data";
// ...
debug("we have " + str + " and it's good");
ideone link.
As far as I know, it creates a string in the first concatenation, and then creates a new one in the second concatenation, which means two inevitable allocations.
Is the following code more performant?
std::string str = "data";
// ...
debug(std::string("we have ") += str += " and it's good");
Or is the first code being optimized by the compiler to something similar?

Related

Without copying, how do I print part of a std::string in C++?

Assume that I want to print the first word. The most obvious way would be like this:
string line = "Hello Hello";
const auto space_iter = find(line.cbegin(), line.cend(), ' ');
cout<<string(line.cbegin(), space_iter)<<endl;
But I'm printing profiling logs for my game at over 60fps, so such memory allocation and copying matters.
I also tried std::span:
string line = "Hello Hello";
const auto space_iter = find(line.cbegin(), line.cend(), ' ');
cout<<span(line.cbegin(), space_iter)<<endl;
But it seems that std::cout can't print a std::span, and gcc gives me 500+ lines of errors.
C++20 gives std::string_view a convenient constructor that takes contiguous iterators. Like those of std::string. Pre-C++20, getting a substring as a string_view was a bit more complex, but now it's pretty trivial:
cout << std::string_view(line.cbegin(), space_iter) << endl;

How to get letter from String by index? C++

Can someone briefly explain how to get a character from index from String in C++.
I need to read the first 3 letters of a String and in java it would bestr.charAt(index) and I have been searching the internet for a solution for 2h now and still don't understand...
can some one please give me an example.
std::string provides operator[] to access a character by index:
https://en.cppreference.com/w/cpp/string/basic_string/operator_at
Example:
const std::string s("hello");
const char c = s[0];
// c is set to ‘h’
substr()
It returns a newly constructed string object with its value initialized to a copy of a substring of this object.
Syntax
substr(pos, pos+len)
Code
std::string str ("Test string"); //string declaration
string sub_string = str.substr(0,3);
String index starts from 0.
Best place to look would be cpluspluc.com: http://www.cplusplus.com/reference/string/string/
You may use as earlier mentioned: http://www.cplusplus.com/reference/string/string/operator[]/
std::string str ("Test string");
for (int i=0; i<str.length(); ++i)
{
std::cout << str[i];
}
Or better yet: http://www.cplusplus.com/reference/string/string/at/
std::cout << str.at(i);
which also checks for a valid position and throws an out of range exception otherwise.
Alternatively you could use http://www.cplusplus.com/reference/string/string/data/
to acces the raw data.
Or if you want to check that your string starts with a specific pattern: http://www.cplusplus.com/reference/string/string/rfind/
std::string str = "Hey Jude!";
if (str.rfind("Hey", 0) == 0) {
// match
}
Another option to obtain a single character is to use the std::string::at() member function. To obtain a substring of a certain length, use the std::string::substr member function.

C++ compose string in one line to give as parameter

In my program I have a program that takes a std::string as parameter. When I call this function I want to give it a large (about 5) composition of strings. Is there a native toString() function that can spit out strings#? Can it be done on one line?
What I want:
std::string a = "sometext";
std::string b = "someothertext";
somefunction(ToString(a+b+"text"));
This works aswell:
std::string a = "sometext";
std::string b = "someothertext";
somefunction(a + b + "text");
std::string already has a operator+ that will concatenate strings. If you have
void foo(std::string some_name) { code in here }
And you want to pass it a combination of a bunch of string you can just use
foo(some_string + another_string + "some text" + even_another_string);
If all of your strings that you want to pass a literal strings then you will either have to add the custom string literal to one of them or convert one to a string
foo("this is a string"s + "another string" + "some more text");
//or
foo(std::string("this is a string") + "another string" + "some more text");

What is the most appropriate way to concatenate with MFC's CString

I am somewhat new to C++ and my background is in Java. I am working on a hdc printing method.
I would like to know the best practice for concatenating a combination of strings and ints into one CString. I am using MFC's CString.
int i = //the current page
int maxPage = //the calculated number of pages to print
CString pages = ("Page ") + _T(i) + (" of ") + _T(maxPage);
I would like it to look like 'Page 1 of 2'. My current code does not work. I am getting the error:
Expression must have integral or enum type
I have found more difficult ways to do what I need, but I want to know if there is a simple way similar to what I am trying. Thanks!
If that's MFC's CString class, then you probably want Format which is a sprintf-alike for it:
CString pages;
pages.Format(_T("Page %d of %d"), i, maxPage);
i.e. you can assemble the string using regular printf-format specifiers substituting in the numbers at runtime.
You can use also stringstream classes
#include <sstream>
#include <string>
int main ()
{
std::ostringstream textFormatted;
textFormatted << "Page " << i << " of " << maxPage;
// To convert it to a string
std::string s = textFormatted.str();
return 0;
}
std::string has all you need:
auto str = "Page " + std::to_string(i) + " of " + std::to_string(maxPage);
As stated correctly in the comment, you can access the underlying C-string via str.c_str(). Here is a live working example.
If you have C++11 you can use std::to_string: std::string pages = std::string("Page ") + std::to_string(i) + (" of ") + std::to_string(maxPage);
If you don't have C++11 you can use an ostringstream or boost::lexical_cast.

Formatting multiple char* strings to an std::string

I have two char* strings and a char* literal that I need to combine into a single std::string. Below is what I am doing. It works, but I don't like the way it looks (3 lines to accomplish it). I am wondering if there is a better way to do it...
std::string strSource = _szImportDirectory;
strSource += "\\";
strSource += _szImportSourceFile;
Thanks for you help!
std::string strSource = std::string(_szImportDirectory) + "\\" + _szImportSourceFile;
Is one obvious way.
Another way is to use std::stringstream:
std::stringstream s;
s << _szImportDirectory << '\\' + _szImportSourceFile;
std::string strSource = s.str()
That's the most flexible and maintainable way to do it but it still requires three lines.
Something like this?
std::string str = std::string(_szImportDirectory).append("\\").append(_szImportSourceFile);
PS: updated with correct code