还有另一种使用stringstream的方法吗?

时间:2020-02-10 13:34:16

标签: c++

我目前正在使用stringstream来传递字符串,但是我想知道是否还有另一种方法?下面是它的完成方式的快照。因为我对c ++还是很陌生,所以我不确定这是否是最好的方法,或者我可能听说过使用字符串流会减慢该过程的速度,并希望了解更多信息。

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();
} 

希望有人可以指导我

1 个答案:

答案 0 :(得分:1)

使用stringstream的方式很好,但是您需要考虑到您的代码在每个stringstream调用中都会创建一个toString()对象,从而导致内存分配。例如,如果您有一千个圆圈要转储为字符串,则将为临时stringstream对象的基础内存缓冲区分配一千个内存,最终将进行一千个释放(如果重新分配,则可能会重新分配)。初始缓冲区不够大)。

很有可能,您将使用toString()进行调试或记录,而性能并不重要。但是,仍有改进的空间。考虑一下您将如何处理Circle::toString()返回的字符串?该字符串很可能会显示,写入文件或通过网络流式传输。您将执行类似cout << circle.toString()的操作。您可以直接将其写入输出流中,而无需创建临时stringstream对象,将其转换为临时字符串并最终将其写入流中。

void Circle::toStream(ostream &os)
{
    os << "Shape [" << index <<"]\n";
    // ...
    os << endl;
}

在头文件中声明operator<<。这样您就可以编写cout << circle;

class Circle {
    // ...
public:
    void toStream(ostream &os);

    friend ostream & operator << (ostream &os, const Circle &c) {
        c.toStream(os);
        return os;
    }
};

如果Circle具有基类,那么在基层上将toStream声明为虚拟是一个好主意:

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;
};

现在,您可以将任何对象打印到任何输出流,而不会降低性能,同时仍保持代码的清洁。

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();

最后,如果您毕竟需要一个字符串,则可以创建一个辅助方法:

string Circle::toString()
{
    stringstream sentence;
    toStream(sentence);
    return sentence.str();
}