5

我想转换这个工作代码:

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 背景,一直在动态创建对象。

谢谢!!

4

3 回答 3

3

构造函数接受对流对象的ostream_iterator<T>const 引用,而临时对象最多可以作为const引用传递(至少在 C++03 中);这个问题很好地解释了这样做的理由。

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

在 Python 中,您可以随时构建/传递东西,因为您总是在处理对引用计数(和垃圾收集)对象的引用。

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

在 C++ 中明确命名所有内容是否更好

不一定——创建临时对象是完全正常的,但你必须知道你可以对它们做什么,不能做什么,引用如何影响它们的生命周期等。

于 2013-02-28T01:58:38.190 回答
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>]
于 2013-02-28T02:01:52.790 回答
0

在 C++ 中,我们也经常即时构造对象,但需要注意所有权问题。

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

有一些方法可以解决这个问题,通过传递给一个身份函数或通过强制转换。但是它们通常会牺牲安全性,因为如果您在持久变量上使用这种机制,它将创建一个悬空引用。

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

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

于 2013-02-28T02:22:53.703 回答