iostream
和其他流类不实际上是类,但是typedef
s,对吧?
这是问题所在,我试图在初始化列表中初始化一个istream
对象,但不幸的是我收到了一个错误,代码如下:
class A
{
public:
A(istream &is=cin): ais(is)
{}
private:
istream ais;
};
无法用g ++编译,错误:
synthesized method ‘std::basic_istream<char, std::char_traits<char> >::basic_istream(const std::basic_istream<char, std::char_traits<char> >&)’ first required here
我搜索了SO,发现了iostream cannot be assigned or copy
。但为什么我不能在初始化列表中初始化它?
Cuz我想,初始化列表会调用对象的构造函数/ copy-constructor,对吗?
答案 0 :(得分:6)
您的代码尝试将一个istream
(传递给构造函数的一个)转换为两个istream
,即传递给构造函数的ais
。istream
。 istream
对象表示实际的流本身。只有一个流,并且无法以某种方式将其转换为两个流。
甚至不清楚这意味着什么。如果流上有一些数据,那么先读取哪个数据流得到它?或者他们都得到了吗?如果是这样,谁或什么重复它?
istream
就像文件本身。如果不将数据从一个文件复制到另一个文件,则无法将一个文件转换为两个文件。但是,您可以根据需要为同一ais
提供尽可能多的引用或指针。您的问题的解决方案可能是{{1}}作为参考。
答案 1 :(得分:4)
您将成员变量声明为:
istream ais;
表示将在初始化列表中调用复制构造函数。这不是特定于初始化列表:您无法在任何地方执行此操作。
您可以将成员变量更改为参考:
istream& ais;
但这意味着您必须确保istream
引用的ais
在A
的生命周期内有效。
答案 2 :(得分:3)
iostream和其他流类实际上不是类,而是typedef,对吗?
是的,但那不相关。
但为什么我不能在初始化列表中初始化它?
因为既不能复制也不能分配。 Ctor init列表并不神奇。要从ais
创建is
,您需要制作副本,而不能。
答案 3 :(得分:2)
stream对象表示数据流的句柄。复制没有意义。另外,这只是复制流的tge基本部分是不正确的:这将切掉有趣的位(虽然你可以通过使用流缓冲区来获取thr实际上有趣的部分)。
如果您的类中包含流,则要在类中初始化的是对流的引用:
std::istream& ais;
当然,这意味着只要您正在使用它,一些外部需要保持流存活。如果这不是您想要或不需要的,您可以让您的课程举行,例如std::ifstream
并将std::string
作为构造函数参数:如果字符串非空,则打开相应的文件。否则,您需要将流rdbuf()
设置为来自std::cin
的<{1}}:
if (name.empty())
ais.open(name.c_str());
else
ais.rdbuf(std::cin.rdbuf());
答案 4 :(得分:1)
除了您已经获得的答案之外,您还可以使用您传入的流的 streambuf 初始化ais
(根据您的定义)(当然,同样的警告与引用一样适用:您必须确保streambuf在对象被破坏之前保持有效。)
使用底层streambuf进行初始化可能是最接近复制您可以执行的流:虽然两者仍然从同一文件读取并使用相同的缓冲(以及streambuf可能执行的其他处理),但所有格式和错误处理标志是分开的。
要使用streambuf初始化ais
,请写下:
class A
{
public:
A(std::istream& is = std::cin):
ais(is.rdbuf())
{
}
private:
std::istream ais;
};
答案 5 :(得分:1)
class A
{
public:
A(istream &is=cin): ais(is)
{}
private:
istream& ais;
};
请注意,该成员是引用类型。正如你所写,你正在制作一份副本来初始化会员。