移动basic_iostream时basic_ostream基数会发生什么变化?

时间:2012-07-03 14:46:25

标签: c++ c++11 iostream

就在我认为我理解C ++ 11中iostreams的多遍移动构造时(感谢https://stackoverflow.com/a/8156356/273767的介绍),我遇到了这个:

§27.7.2.5.1[iostream.cons] / 3

  

basic_iostream(basic_iostream&& rhs);

     

3效果:通过使用basic_istream构建move(rhs)基类,从rvalue rhs移动构造。

那么另一个基地basic_ostream会发生什么?

我看到libc ++给了std::basic_ostream一个protected default constructor,在这里调用(并且与正常constructor of basic_iostream中的§27.7.2.5.1/ 1的字母相矛盾),什么都不做。那应该是怎么回事?

2 个答案:

答案 0 :(得分:7)

正如您所指出的那样,规范为:

explicit basic_iostream(basic_streambuf<charT,traits>* sb);

初始化两个碱基。我从来没有对此表示满意:

http://cplusplus.github.com/LWG/lwg-closed.html#135

因为它导致在同一个虚拟基础对象上调用单个 basic_ios::init()函数两次。委员会裁定这种双重初始化是无害的。我强烈反对,我拒绝执行有关此细节的规范。但是规范说要加倍初始化虚拟基类。

当指定basic_iostream移动构造函数时,我就在驾驶员座位上。所以我指出了我最好的想法(不加倍地初始化basic_ios)。该决定尚未受到挑战,但最终可能会受到挑战。

请注意,为了避免双重初始化,必须精心设计basic_ostream默认构造函数以完全不做任何事情。没什么,我真的没什么意思。没有零初始化:

protected:
    _LIBCPP_ALWAYS_INLINE
    basic_ostream() {}  // extension, intentially does not initialize

幸运的是,basic_ostream的基类实际上被指定为在其默认构造函数中不执行任何操作。所以一切正常:basic_ostream默认构造,不触及内存。然后,派生客户只需调用init(basic_streambuf<char_type, traits_type>*) 一次即可实际构建basic_ios / ios_base

这是一个非常混乱的设计。通过拒绝对虚拟基础进行双重初始化,我觉得libc ++使设计变得不那么混乱,而且更加可靠。这是移动构造函数的标准行为,而不是构造函数采用streambuf*的标准行为。

答案 1 :(得分:3)

我同意霍华德的说法,这对标准规范来说是个蠢事。

在我的实现中,我选择使用对构造函数扩展的更具体的调用

basic_iostream(basic_iostream&& _Other)
   : std::basic_istream<char_type, traits_type>(std::move(_Other)),
     std::basic_ostream<char_type, traits_type>(basic_ostream::_NoInit)
{ }

在基类中使用特殊的protected构造函数

protected:    
    // special interface for basic_iostream

    enum __no_init_t { _NoInit };

    basic_ostream(__no_init_t)
    { }

净效果是一样的。