I'm bit confused why the std::move(std::string) not making the passed std::string argument to an empty state (I mean std::string size as 0 and its internal buffer to point to nullptr after call to std::move(std::string)). This is a sample code
#include <iostream>
#include <string>
void print(std::string& str) {
std::cout << "lref\n";
std::cout << str << "\n" << std::endl;
}
void print(const std::string& str) {
std::cout << "const lref\n";
std::cout << str << "\n" << std::endl;
}
void print(std::string&& str) {
std::cout << "rref\n";
std::cout << str << "\n" << std::endl;
}
int main() {
std::string str_a = "Hello, ";
std::string str_b = "world!";
print(str_a);
print(str_b);
print(str_a + str_b);
print(std::move(str_a));
print(str_a); // was expecting str_a to be empty but still prints Hello,
return 0;
}
std::move is not moving anything. It cast its argument to an rvalue-reference. To actually move you need to pass str as rvalue-reference to move constructor(or move assignment) of another string as below.
std::string new_str(std::move(str));
print(str);
Related
This is my code:
#include <iostream>
#include <sstream>
void serialize(std::ostream& os)
{
int r1 = 10;
int r2 = 12;
os.write(reinterpret_cast<char const*>(&r1), sizeof(r1));
os.write(reinterpret_cast<char const*>(&r2), sizeof(r2));
}
int main()
{
std::stringstream ss;
serialize(ss);
std::cout<<" Buffer length : " << ss.str().length() <<'\n'; //This print correct length
const char *ptrToBuff = ss.str().c_str();// HERE is the problem. char * does not contain anything.
std::cout <<ptrToBuff; // NOTHING is printed
}
How to get a char pointer to the stream buffer?
The problem is std::cout << ptrToBuff; does not print anything
A pointer to the stream will leave a dangling pointer, you can copy the string though:
const std::string s = ss.str();
And then point your const char* to it:
const char *ptrToBuff = s.c_str();
In your serialize function you should use << operator to write to ostream:
os << r1 << " " << sizeof(r1) << std::endl;
os << r2 << " " << sizeof(r2) << std::endl;
So the whole code will be: (see here)
void serialize(std::ostream& os)
{
int r1 = 10;
int r2 = 12;
os << r1 << " " << sizeof(r1) << std::endl;
os << r2 << " " << sizeof(r2) << std::endl;
}
int main()
{
std::stringstream ss;
serialize(ss);
std::cout<<"Buffer length : " << ss.str().length() <<'\n';
const std::string s = ss.str();
const char *ptrToBuff = s.c_str();
std::cout << ptrToBuff;
}
I was going through the c++ website tutorials as a nice compliment to a college course I'm taking this semester (beginner). While learning about copy constructors and destructors, I came across this section of code:
// destructors
#include <iostream>
#include <string>
using namespace std;
class Example4 {
string* ptr;
public:
// constructors:
Example4() : ptr(new string) {}
Example4 (const string& str) : ptr(new string(str)) {}
// destructor:
~Example4 () {delete ptr;}
// access content:
const string& content() const {return *ptr;}
};
int main () {
Example4 foo;
Example4 bar ("Example");
cout << "bar's content: " << bar.content() << '\n';
return 0;
}
Now, I understand the destructor part, but the getter for the string member confused me. Why return a reference (alias) to the object (string in this case)?
// access content:
const string& content() const {return *ptr;}
What is the difference between that, and just returning the string?
string content() const {
return *ptr;
}
Is returning a const alias more efficient? Are you returning just the address of the string, or the string itself? What about when just returning the string, are you returning the entire string? Thanks.
Returning a string would be undesirable for two reasons:
It means an unnecessary copy of the string is performed, which is bad for performance
It also means that someone might attempt to modify the returned string, thinking that they modify the actual member of the class - const reference would not allow this, and trigger a compilation error.
the getter for the string member confused me. Why return a
reference (alias) to the object (string in this case)?
const string& content() const {return *ptr;}
What is the difference between that [return a reference],
and just returning the string?
string content() const { return *ptr;}
And you might ask if there is a difference between that
and returning only the pointer
const string* content() const { return ptr;}
I find no advantage of one over the other(s).
Well, maybe consider the scenario where the string contains 26 million chars, you probably want to avoid copying that.
But there is another issue (or maybe 2) you should be aware of, if only to evaluate what you have learned here.
On Lubuntu 18.04, using g++ (Ubuntu 7.3.0-27), a string s, with no data,
std::string s;
cout << sizeof(s) << " " << s.size() << endl;
Reports the numbers "32 0".
std::string s ("01234567890123456789");
cout << sizeof(s) << " " << s.size() << endl;
Reports values "32 20"
{
std::string s;
for (int i=0; i<1000000; i++)
{
for (char j='A'; j<='Z'; j++)
s.push_back(j);
}
cout << " " << sizeof(s) << " " << s.size() << endl;
}
This reports the values "32 26000000"
1 million alphabets
s is still only 32 bytes
From this, you may conclude a) that an instance of 'string' occupies 32 bytes regardless of data. b) because all the data resides elsewhere c) so some of the 32 bytes in a std::string instance is a pointer to where in dynamic memory the chars resides.
Hmmm.
If the obj instance is only 32 bytes, then you might ask why does Example4 use a pointer to place this SMALL object (the string instance) into the dynamic memory ... using 8 bytes to find 32, and then needing a second reference (of some pointer inside of the string instance) to reach the char's of Example4 string.
In the same way, a std::vector is 24 bytes (regardless of how many elements, and regardless of how big the elements). std::vector takes care of memory management, so that you don't have to.
Perhaps this lesson is meant to help you discover and evaluate what is in dynamic memory, and what is in automatic memory, to improve your choices.
The key idea, is that STL library containers handle dynamic memory for you, to greatly simplify your effort.
Or, perhaps the professor wants you to know more about the tools you are using. The standard containers, in some ways, isolate you from how this stuff works. Perhaps this assignment is to get a glimpse into what std::string does.
// here is some "g++ -std=c++17" code to single step through, illustrating several of the ideas
#include <iostream>
using std::cout, std::endl;
#include <sstream>
using std::stringstream;
#include <iomanip>
using std::setfill, std::setw;
#include <string>
using std::string;
#include <cstring>
using std::strlen;
class Example4
{
string* ptr;
public:
Example4() : ptr(new string) {}
Example4 (const string& str) : ptr(new string(str)) {}
~Example4 () {delete ptr;}
// access content:
const string& content() const {return *ptr;}
const string* contentP() const {return ptr;}
string show(string lbl)
{
stringstream ss;
ss << "\n " << lbl
<< " . 5 4 3 2 1"
<< "\n . '09876543210987654321098765432109876543210987654321'"
<< "\n " << "*ptr : '" << *ptr << "'"
<< "\n " << "(*ptr).size() : " << (*ptr).size()
<< "\n " << " ptr->size() : " << ptr->size()
<< "\n " << "strlen((*ptr).c_str()) : " << strlen((*ptr).c_str())
<< "\n " << "strlen(ptr->c_str()) : " << strlen(ptr->c_str())
<< "\n\n " << "sizeof(*ptr) : " << sizeof(*ptr)
<< " # 0x" << ptr << ',' // where ptr points to
<< "\n " << "sizeof (ptr) : " << sizeof(ptr)
<< "\n\n";
return ss.str();
}
};
class T996_t
{
public:
int operator()() { return exec(); }
private: // methods
int exec()
{
Example4 e4("Now is the time to answer all questions01234567890");
cout << "\n " << e4.show("Example4")
<< "\n '" << e4.content() << "'"
<< "\n '" << *e4.contentP() << "'\n\n"
<< endl;
{
std::string s;
cout << " " << sizeof(s) << " " << s.size() << endl;
}
{
std::string s("01234567890123456789");
cout << " " << sizeof(s) << " " << s.size() << endl;
}
{
std::string s;
for (int i=0; i<1000000; i++)
{
for (char j='A'; j<='Z'; j++)
s.push_back(j);
}
cout << " " << sizeof(s) << " " << s.size() << endl;
}
return 0;
}
}; // class T996_t
int main(int, char**) { return T996_t()(); }
This code compiles and runs on my Lubuntu. The compile command built by my make file starts with:
g++ -std=c++17 -m64 -ggdb
The following dummy example may not really make sense in real world. But it explains the question. I have a class Foo with members firstname and lastname. The function ForEachMessage takes a lambda. I want it to capture only the firstname of Foo but not lastname. How do I achieve that?
#include <iostream>
#include <vector>
#include <functional>
using namespace std;
vector<string> messagesList;
void ForEachMessage(function<void(const string&)>callBack)
{
for (const auto& str : messagesList) {
callBack(str);
}
}
class Foo {
public:
std::string firstname;
std::string lastname;
void say() {
ForEachMessage([this](const std::string& someMessage)
{
cout << firstname << ": " << someMessage << endl;
});
// Error: firstname in capture list doesn't name a variable
// ForEachMessage([firstname](const std::string& someMessage)
// {
// cout << firstname << ": " << someMessage << endl;
// });
// Error: expect ',' or ']' in lambda capture list
// ForEachMessage([this->firstname](const std::string& someMessage)
// {
// cout << firstname << ": " << someMessage << endl;
// });
}
};
int main(int argc, const char * argv[]) {
Foo foo;
foo.firstname = "Yuchen";
foo.lastname = "Zhong";
messagesList.push_back("Hello, World!");
messagesList.push_back("Byebye, World!");
foo.say();
return 0;
}
You can use the C++14 named capture for this:
ForEachMessage([bla=firstname](const std::string& someMessage)
{
cout << bla << ": " << someMessage << endl;
});
(See it live) To avoid a copy, you may also capture by reference with [&bla=firstname] instead. For a discussion on how to capture by const&, see this question and in particular this answer.
(Remark: The local name can, but need not be different from the member name.)
Create a reference to firstname
const std::string& rfn = firstname;
And capture the reference
ForEachMessage([rfn](const std::string& someMessage)
{
cout << rfn << ": " << someMessage << endl;
}
I have been looking for a solution but couldn't find what I need/want.
All I want to do is pass a stream intended for std::cout to a function, which manipulates it. What I have used so far is a template function:
template<typename T>
void printUpdate(T a){
std::cout << "blabla" << a << std::flush;
}
int main( int argc, char** argv ){
std::stringstream str;
str << " hello " << 1 + 4 << " goodbye";
printUpdate<>( str.str() );
return 0;
}
What I would prefer is something like:
printUpdate << " hello " << 1 + 4 << " goodbye";
or
std::cout << printUpdate << " hello " << 1 + 4 << " goodbye";
I was trying to do:
void printUpdate(std::istream& a){
std::cout << "blabla" << a << std::flush;
}
but that gave me:
error: invalid operands of types ‘void(std::istream&) {aka void(std::basic_istream<char>&)}’ and ‘const char [5]’ to binary ‘operator<<’
You can't output data to an input stream, just not a good thing to do.
Change:
void printUpdate(std::istream& a){
std::cout << "blabla" << a << std::flush;
}
To:
void printUpdate(std::ostream& a){
std::cout << "blabla" << a << std::flush;
}
Note the stream type change.
Edit 1:
Also, you can't output a stream to another stream, at least std::cout.
The return value of << a is a type ostream.
The cout stream doesn't like being fed another stream.
Change to:
void printUpdate(std::ostream& a)
{
static const std::string text = "blabla";
std::cout << text << std::flush;
a << text << std::flush;
}
Edit 2:
You need to pass a stream to a function requiring a stream.
You can't pass a string to a function requiring a stream.
Try this:
void printUpdate(std::ostream& out, const std::string& text)
{
std::cout << text << std::flush;
out << text << std::flush;
}
int main(void)
{
std::ofstream my_file("test.txt");
printUpdate(my_file, "Apples fall from trees.\n");
return 0;
}
Chaining Output Streams
If you want to chain things to the output stream, like results from functions, the functions either have to return a printable (streamable object) or the same output stream.
Example:
std::ostream& Fred(std::ostream& out, const std::string text)
{
out << "--Fred-- " << text;
return out;
}
int main(void)
{
std::cout << "Hello " << Fred("World!\n");
return 0;
}
I'm having trouble with std::stringstream. My function as seen below returns absolutely nothing. Even when trying a stringstream outside of the template function it still returns nothing when .str() is called.
template < class T > std::string toString( const T &t )
{
std::stringstream temp;
temp << t;
std::cout << temp.str() << std::endl;
return temp.str();
}
std::string test = "test" + toString( 1 );
std::cout << test << std::endl;
std::stringstream stream;
stream << "test" << 1;
std::cout << stream.str() << std::endl;
Both of these output only "test"
Fixed
Had to remove _GLIBCXX_DEBUG and _GLIBCXX_DEBUG_PEDANTIC from my preprocessor macros.
Try ostringstream instead of stringstream.
== UPDATE ==
I compiled your code with GCC 4.6.1, and it works as-is:
#include <iostream>
#include <sstream>
using namespace std;
template < class T > std::string toString( const T &t )
{
std::stringstream temp;
temp << t;
std::cout << temp.str() << std::endl;
return temp.str();
}
int main()
{
std::string test = "test" + toString( 1 );
std::cout << test << std::endl;
std::stringstream stream;
stream << "test" << 1;
std::cout << stream.str() << std::endl;
return 0;
}
Output:
1
test1
test1
#include <iostream>
#include <sstream>
#include <string>
template < class T > std::string toString( const T &t )
{
std::stringstream temp;
temp << t;
std::cout << temp.str() << std::endl;
return temp.str();
}
int main(){
std::string test = "test" + toString( 1 );
std::cout << test << std::endl;
std::stringstream stream;
stream << "test" << 1;
std::cout << stream.str() << std::endl;
}
Outputs
1
test1
test1
For me with Clang 3.1, GCC 4.4.5 and MSVC 10, so your problem lies elsewhere. Please try just the code above in a new project and see if the problem persists. If not, the suggestions by #Industrial-antidepressant sounds quite realistic, i.e. that you have a better matching overload lying around somewhere.