Reputation: 11
I am currently using stringstream
to pass a string over but I was wondering if there is another way of doing it? below is a snip shot of how it's done. as I am still quite new to c++, I am not sure if this is the best way to do it or there could be an alternative as I heard using string stream slows down the process and was hoping to learn more.
string Circle::toString()
{
stringstream sentence;
sentence << "Shape [" << index <<"]" << endl;
sentence << "Name: " << name << endl;
if (containsWarpSpace == false)
sentence << "Special Type: NS" << endl;
else
sentence << "Special Type: WS" << endl;
sentence << "Area: " << area << " units square" << endl;
sentence << "Vertices: " << endl;
sentence << "Point[0]: (" << center[0] << ", " << center[1] << ")" << endl;
sentence << endl;
sentence << "Points on perimeter: " << endl;
bool trueFalse= false;
int count = 0;
for ( int y = center[1] - unit; y < center[1] + unit + 1; y++)
{
for ( int x = center[0] - unit; x < center[0] + unit + 1; x++)
{
trueFalse = isPointOnShape (x, y);
if (trueFalse == true)
{
if (count %6 == 0)
sentence << "(" << x << ", " << y << ")";
else
sentence << ", (" << x << ", " << y << ")";
count++;
if (count %6 == 0)
sentence << endl;
}
}
}
if (count == 0)
sentence << "none!";
sentence << endl;
count = 0;
sentence << "Points within shape: " << endl;
for (int y = center[1] - unit; y < center[1] + unit + 1; y++)
{
for ( int x = center[0] - unit; x < center[0] + unit + 1; x++)
{
trueFalse = isPointInShape (x, y);
if (trueFalse == true)
{
if (count %6 == 0)
sentence << "(" << x << ", " << y << ")";
else
sentence << ", (" << x << ", " << y << ")";
count++;
if (count %6 == 0)
sentence << endl;
}
}
}
if (count == 0)
sentence << "none!";
sentence << endl;
return sentence.str();
}
hope some one could guide me on this
Upvotes: 1
Views: 243
Reputation: 701
The way you are using stringstream
is fine, but you need to consider that your code creates a stringstream
object in every toString()
call, which, in turn, leads to memory allocation. For example, if you have a thousand circles to dump into a string, then there will be a thousand memory allocations for the underlying memory buffer of a temporary stringstream
object, eventually following by a thousand deallocations (and maybe reallocations if the initial buffer isn't big enough).
Most likely, you will be using toString()
for debugging or logging, where performance doesn't matter that much. However, there is room for improvement. Think about what you're going to do with the string returned by Circle::toString()
? Most likely, the string is going to be displayed, written to a file, or maybe streamed via a network. You'll be doing something like cout << circle.toString()
. Instead of creating a temporary stringstream
object, converting it into a temporary string, and finally writing it into a stream, you can write it into the output stream directly.
void Circle::toStream(ostream &os)
{
os << "Shape [" << index <<"]\n";
// ...
os << endl;
}
In the header file declare operator<<
. That allows you writing cout << circle;
class Circle {
// ...
public:
void toStream(ostream &os);
friend ostream & operator << (ostream &os, const Circle &c) {
c.toStream(os);
return os;
}
};
If Circle has a base class, then it is a good idea to declare toStream
as virtual on the base level:
class Object {
public:
virtual ~Object() = default;
virtual void toStream(ostream &os) = 0;
friend ostream &operator << (ostream &os, const Object &obj) {
obj.toStream(os);
return os;
}
};
class Circle : public Object {
public:
void toStream(ostream &os) override;
};
class Rectangle : public Object {
public:
void toStream(ostream &os) override;
};
Now you can print any object to any output stream without performance drawback while still keeping your code clean.
Circle circle1, circle2;
Rectangle rectangle;
// ...
// print circle to stdout
cout << "My circles:\n" << circle1 << circle2;
cout << "My rectangle:\n" << rectangle;
// write circles to a file
ofstream myfile;
myfile.open ("circle.log");
myfile << circle1 << circle2;
myfile.close();
Finally, if you need a string after all, then you can create a helper method:
string Circle::toString()
{
stringstream sentence;
toStream(sentence);
return sentence.str();
}
Upvotes: 1