临时ostream对象的c ++问题

时间:2013-02-28 01:52:01

标签: c++ temporary-objects anonymous-objects

我想改变这个工作代码:

ofstream outfile("my_file.txt");
copy(v.begin(), v.end(), ostream_iterator<int>(outfile));

进入这个:

copy(v.begin(), v.end(), ostream_iterator<int>(ofstream("my_file.txt")));

换句话说,我使用ofstream对象的“匿名”或未命名版本。

两个问题:

(1)为什么第二次尝试失败?

(2)第二次尝试在风格上是否很好,或者在C ++中保持所有明确命名的更好?我来自Python背景,其中对象是一直在创建的。

谢谢!

3 个答案:

答案 0 :(得分:3)

ostream_iterator<T>构造函数将非const 引用带到流对象,而temporaries最多可以作为const引用传递(至少在C ++ 03);在this question中很好地解释了这一点的基本原理。

顺便说一句,这里没有太多关于如何传递流的选择:const引用没有意义(ostream_iterator 到修改流),并且普通ostream是不可接受的,因为它是不可复制的(切片会杀死多态)。

在Python中,您可以随时处理构建/传递内容,因为您始终处理引用引用计数(和垃圾收集)物体

C ++对象语义完全不同 - 对象对象,而不是引用;要获得类似于Python的语义,您必须使用new动态分配每个对象,并将它们包裹在shared_ptr<T>中。

  

在C ++中保持所有明确命名的

更好

不一定 - 创造临时工作是完全正常的,但你必须意识到你能做什么,不能做什么,参考如何影响他们的生命等等。

答案 1 :(得分:0)

我从编译器中收到以下错误消息,解释了它。

std::ostream_iterator的构造函数采用非const引用。没有一个版本的构造函数采用std :: ofstream。

Untitled 33.cpp:21: error: no matching function for call to ‘std::ostream_iterator<int, char, std::char_traits<char> >::ostream_iterator(std::ofstream)’
/usr/include/c++/4.2.1/bits/stream_iterator.h:185: note: candidates are: std::ostream_iterator<_Tp, _CharT, _Traits>::ostream_iterator(const std::ostream_iterator<_Tp, _CharT, _Traits>&) [with _Tp = int, _CharT = char, _Traits = std::char_traits<char>]
/usr/include/c++/4.2.1/bits/stream_iterator.h:181: note:                 std::ostream_iterator<_Tp, _CharT, _Traits>::ostream_iterator(std::basic_ostream<_CharT, _Traits>&, const _CharT*) [with _Tp = int, _CharT = char, _Traits = std::char_traits<char>]
/usr/include/c++/4.2.1/bits/stream_iterator.h:169: note:                 std::ostream_iterator<_Tp, _CharT, _Traits>::ostream_iterator(std::basic_ostream<_CharT, _Traits>&) [with _Tp = int, _CharT = char, _Traits = std::char_traits<char>]

答案 2 :(得分:0)

在C ++中,我们还经常构建对象,但需要考虑所有权问题。

ostream_iterator<int>(ofstream("my_file.txt"))的问题是临时对象被传递给构造函数,但构造的ostream_iterator对象并不承担临时对象的所有权。如果ostream_iterator不是临时的,它将继续在下一行代码中保留无效引用。

通过传递身份功能或通过强制转换,可以解决这个问题。但是他们通常牺牲安全性,因为如果你在持久变量上使用这样的机制,它将创建一个悬空引用。

当你有几个通过引用链接的对象,没有容器包含的关系时,当前的C ++最佳实践是使用命名对象,而不是临时对象。

如果您不喜欢这样,您可以选择更频繁地使用共享指针。该模式允许在多个引用之间共享所有权,并隐藏容器。但这不是iostream的一部分,而且作为设计决定,这里有点可疑。