Làm thế nào để tái sử dụng một hệ thống xương?


Câu trả lời:


156

Tôi đã sử dụng một chuỗi rõ ràng và str trong quá khứ:

// clear, because eof or other bits may be still set. 
s.clear();
s.str("");

Điều này đã làm điều này cho cả hai chuỗi đầu vào và đầu ra. Ngoài ra, bạn có thể xóa thủ công, sau đó tìm kiếm trình tự phù hợp để bắt đầu:

s.clear();
s.seekp(0); // for outputs: seek put ptr to start
s.seekg(0); // for inputs: seek get ptr to start

Điều đó sẽ ngăn chặn một số phân bổ lại được thực hiện bằng strcách ghi đè bất cứ thứ gì trong bộ đệm đầu ra hiện tại thay thế. Kết quả là như thế này:

std::ostringstream s;
s << "hello";
s.seekp(0);
s << "b";
assert(s.str() == "bello");

Nếu bạn muốn sử dụng chuỗi cho các hàm c, bạn có thể sử dụng std::ends, đặt null kết thúc như thế này:

std::ostringstream s;
s << "hello";
s.seekp(0);
s << "b" << std::ends;
assert(s.str().size() == 5 && std::strlen(s.str().data()) == 1);

std::endslà một bản tường thuật của phần không dùng nữa std::strstream, có thể ghi trực tiếp vào một mảng char mà bạn đã phân bổ trên ngăn xếp. Bạn phải chèn null kết thúc bằng tay. Tuy nhiên, std::endstôi không phản đối, tôi nghĩ bởi vì nó vẫn hữu ích như trong các trường hợp trên.


Tôi đang cố gắng sử dụng s.str () với một khung hình. Kích thước đang làm rối tung nó lên (tôi có thể thấy ký tự đầu tiên là null nhưng nó in nhiều hơn). Có một cách tốt để sửa chữa chiều dài str? tôi đang sử dụng s.str (). c_str (); ATM và nó hoạt động độc đáo

Trên thực tế ngay cả điều này là không chính xác. Tôi chỉ làm s.str("");thay thế. auto str = s.str(); auto cstr = str.c_str(); file << cstr; s.clear(); s.seekp(0); s << ends;

std :: kết thúc không hoạt động đối với tôi trong thử nghiệm google boost::any a = 1; std::ostringstream buffer; buffer << a << std::ends; EXPECT_EQ( buffer.str(), "any<(int)1>" ); TestUtilsTest.cpp:27: Failure Expected: buffer.str() Which is: "any<(int)1>\0" To be equal to: "any<(int)1>" và nếu tôi sử dụng lại với các chuỗi có độ dài khác nhau, tôi sẽ nhận được các bit còn lại
David van Laatum

Thay thế là câu trả lời thực sự nếu bạn muốn tránh tái phân bổ. Và nếu bạn muốn thực sự "bắt đầu mới" mà không cần tái phân bổ, chỉ cần gọi lại tìm kiếm (0) sau khi gửi std :: end. s.seekp(0); s << std::ends; s.seekp(0);
Chip Grandits

5

Có vẻ là ostr.str("")cuộc gọi thực hiện các mẹo.


9
Đáng để chỉ ra rằng điều này sẽ không sử dụng lại bộ đệm cơ bản từ hệ thống xương - nó chỉ gán một bộ đệm mới. Vì vậy, trong khi bạn đang sử dụng lại đối tượng xương, bạn vẫn đang phân bổ hai bộ đệm. Tôi không nghĩ rằng hệ thống xương được thiết kế để tái sử dụng theo cách bạn dự định.
razlebe

2
Nó cũng không xóa trạng thái, đó là những gì .clear () làm. Tôi đồng ý, nó thực sự không có nghĩa là được sử dụng như thế này. Chỉ cần tạo một cái mới để chắc chắn. Chỉ khi bạn hồ sơ, bạn sẽ tìm ra nếu nó làm cho bất kỳ sự khác biệt.
Brian Neal

1
sgreeve, Brian, đúng vậy. Tuy nhiên, lưu ý rằng phương thức của litb ở trên yêu cầu sử dụng std :: end. Nó sử dụng lại bộ đệm, nhưng làm cho bạn mã khác với thông thường với các chuỗi chuỗi (thông thường bạn không sử dụng std :: end).
Diego Sevilla

2

Nếu bạn định xóa bộ đệm theo cách sẽ khiến nó bị xóa trước khi sử dụng lần đầu tiên, bạn sẽ cần thêm một cái gì đó vào bộ đệm trước w / MSVC.

struct Foo {
    std::ostringstream d_str;
    Foo() { 
        d_str << std::ends;   // Add this
    }
    void StrFunc(const char *);
    template<class T>
    inline void StrIt(const T &value) {
        d_str.clear();
        d_str.seekp(0);  // Or else you'll get an error with this seek
        d_str << value << std::ends;
        StrFunc(d_str.str().c_str());  // And your string will be empty
    }
};

Tôi không thấy hành vi thất bại trên VS2012. Hơn nữa, gọi clearsẽ gây ra sự failbittrở thành bộ nếu dòng trống. Trong khi chỉ cần gọi seekpnên trở lại nếu không có luồng.
Jonathan Mee

0

Bạn không. Sử dụng hai luồng được đặt tên khác nhau cho rõ ràng và để trình biên dịch tối ưu hóa tìm ra rằng nó có thể sử dụng lại luồng cũ.


4
xem xét trường hợp sử dụng trong đó mã đang lặp qua dữ liệu đầu vào, ghi vào một ostringstream(dựa trên dữ liệu đã đọc) và sau đó phải viết chuỗi được xây dựng ở ostringstreamđâu đó theo thời gian (ví dụ sau khi đọc một chuỗi ký tự nhất định) và bắt đầu xây dựng một chuỗi mới.
Andre Holzner
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.