C++ 初始化构造函数初始值设定项中的非常量类型时出错?

C++ 初始化构造函数初始值设定项中的非常量类型时出错?,c++,C++,错误: error: invalid initialization of non-const reference of type ‘std::istream& {aka std::basic_istream<char>&}’ from an rvalue of type ‘std::ifstream {aka std::basic_ifstream<char>}’ 如果我将私人fin成员设置为常量,则此操作有效。有人能解释一下原因吗?因为您正在初始化来自

错误:

error: invalid initialization of non-const reference of type ‘std::istream& {aka std::basic_istream<char>&}’ from an rvalue of type ‘std::ifstream {aka std::basic_ifstream<char>}’

如果我将私人fin成员设置为常量,则此操作有效。有人能解释一下原因吗?

因为您正在初始化来自临时用户的引用。只有
const
引用可以做到这一点……尽管它实际上不“工作”,因为您有一个悬空引用。引用绑定的这种特殊用法不会延长临时用户的使用寿命

[C++14:12.2/5]:
[…]引用绑定到的临时对象或作为引用绑定到的子对象的完整对象的临时对象在引用的生存期内持续存在,但以下情况除外:

  • 构造函数的ctor初始值设定项(12.6.2)中与引用成员的临时绑定将持续存在,直到构造函数退出
  • [……]
实现这一点的常规方法是首先将流接受到构造函数中:

MyClass(std::istream& strm, const char quote, const char sep)
  : fin(strm), owns_stream(true), sep(sep), quote(quote)
{}
然后:

这对于您的用户来说更加灵活

否则,如果您希望特别强制使用
std::ifstream
,只需存储一个实际的
std::ifstream
,并删除整个临时/参考业务:

class MyClass {
public:
   MyClass(const std::string& filename)
      : fin(filename)
   {}

private:
  std::ifstream fin;
};

好的,有道理。我有另一个接受流的构造函数,为了方便起见,我最想要的是第二个构造函数,因为用户确实不想管理流本身的生存期。对不起,我想我已经标记为answer了。我能想到的唯一合理的方法是在内部使用istream指针,如果他们传入文件名,就在堆上分配它;如果他们传入流,就在堆上分配地址(并且根据我是否拥有所有权进行删除)。“我还缺少其他方法吗?”弗雷德:这可能是我会做的(如果我认为这真的值得麻烦的话)。
std::ifstream ifs("/tmp/something");
MyClass obj(ifs);
class MyClass {
public:
   MyClass(const std::string& filename)
      : fin(filename)
   {}

private:
  std::ifstream fin;
};