簡體   English   中英

為什么std :: basic_ostream :: operator <<不符合const資格?

[英]why is std::basic_ostream::operator<< not const-qualified?

首先,用一個例子來說明我的問題背后的道德:以下代碼將無法編譯,因為std :: basic_ostream :: operator <<不是const限定的。 https://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-html-USERS-3.4/ostream-source.html顯示操作符不是const限定的。)

我使用GNU g ++ 6.4.0編譯器進行編譯,並帶有--std = c ++ 11標志。

#ifndef TEST_H
#define TEST_H
#include<string>
#include<iostream>
using namespace std;
class ChessPiece{
    const string name;
    const int side;
public:
    ChessPiece(const string&,const int);
    void printPiece(const ostream&) const;
};
#endif // TEST_H

...和test.cpp。

#include"test.h"
ChessPiece::ChessPiece(const string& s,const int bw): name{s}, side{bw} {}
void ChessPiece::printPiece(const ostream& S=cout) const{
    S << "a " << (side==1?"white ":"black ") << name << endl;
}
int main(){
    ChessPiece p{string("pawn"),-1}; // a black pawn
    p.printPiece();
}

但是,我不確定為什么應該首先發生這類錯誤,即使在上面的代碼中operator <<在邏輯上是const 是的,顯而易見的答案是“ operator<<以某種方式更改了std::ostream的內部狀態”。

但是,我知道,只要使const限定的函數在邏輯上是const ,就可以通過使成員mutable而改變類的內容。 我也知道std::ostream實例在調用其operator<<之前和之后在邏輯上不會有任何區別。 (如果我寫的任何東西是錯誤的,請指出。謝謝)

改寫,

為什么邏輯const std :: basic_ostream :: operator <<不是const限定的,而是使某些成員可變?

先感謝您。

在以外部可見的方式調用其operator<<之后, std::ostream 有所不同。 大多數情況下, tellp方法將返回更新后的值(類似地,使用cur作為第二個參數的seekp結果也會有所不同)。

即使它是流輸出(所以“位置”是沒有意義的概念),各種狀態位也總是可以更改的,並且通過goodbadfaileof方法再次成為外部可見狀態的一部分。

此外, ostream的緩沖區具有的行為(包括被完全換出的能力)隨着將內容寫入其中而無法預料地有所不同。 交換后備緩沖區的行為完全取決於其是否為空。 如果為非空,則不會寫入某人寫入的數據。 由於寫入更多類型的數據可以從空狀態切換到非空緩沖區狀態(將少於緩沖區大小的字節寫入空緩沖區而沒有隱式刷新),也可以從非空狀態切換為空(如果通過填充緩沖區觸發刷新)緩沖區或行緩沖流上的換行符),您總是在更改緩沖區的可見狀態。

你說:

我也知道std::ostream實例在調用其operator<<之前和之后在邏輯上不會有任何區別。

這是查看std::ostream的一種方法。 另一種看待它的方法是它是設備的接口,即文件,控制台,字符串等。如果該接口中的成員函數更改了基礎設備,則將該成員函數設置為const會產生誤導。成員函數。

const的概念是概念性的。 看一下我的答案 ,它對這個主題進行了一些探討。 是的,可以使operator<<函數與const std::stream對象一起使用,但更有意義的是,它們不是。 他們正在更改為其提供接口的基礎設備,並且IMO最好與std::ostream類型的非const對象一起使用。

讓我們看一下這樣的代碼:

os << data;
if( !os ) throw std::runtime_exception( "io error" );

盡管通常會忽略operator<<結果,但可能需要檢查輸出是否成功。 編譯器很可能無法優化此檢查,但是對於我來說,作為讀者,它還是不清楚的,為什么在調用const方法后為什么需要重新檢查對象的狀態。 因此,將這些方法標記為const將損害接口的可讀性,並且不會帶來任何好處,並且顯然這些調用在概念上不是const

注意:添加了可變成員以優化const方法調用而無需更改可觀察到的行為(昂貴的操作的緩存結果,如果對象的狀態未更改,則返回緩存的值),在這里使用mutable會簡單地濫用const方法的概念

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM