简体   繁体   English

临时ostream对象的c ++问题

[英]c++ problems with temporary ostream objects

I thought to transform this working code: 我想改变这个工作代码:

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

into this: 进入这个:

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

In other words, I use an "anonymous", or unnamed, version of the ofstream object. 换句话说,我使用ofstream对象的“匿名”或未命名版本。

Two questions: 两个问题:

(1) Why does the second attempt fail? (1)为什么第二次尝试失败?

(2) Is the second attempt even good stylistically, or is it better in C++ to keep everything explicitly named? (2)第二次尝试在风格上是否很好,或者在C ++中保持所有明确命名的更好? I'm coming from a Python background, where objects are created on the fly all the time. 我来自Python背景,其中对象是一直在创建的。

Thanks!! 谢谢!!

The ostream_iterator<T> constructor takes a non- const reference to a stream object, while temporaries can be passed at most as const references (at least in C++03); ostream_iterator<T>构造const对流对象采用非const 引用 ,而temporaries最多可以作为const引用传递(至少在C ++ 03中); the rationale for this is well explained in this question . 这个问题中很好地解释了这个的基本原理。

By the way, here there wasn't much choice about how to pass the stream: a const reference wouldn't have made sense (the ostream_iterator has to modify the stream), and a plain ostream isn't acceptable because it is non-copyable (slicing would kill polymorphism). 顺便说一句,这里没有太多关于如何传递流的选择:一个const引用没有意义( ostream_iterator 必须修改流),而普通的ostream是不可接受的,因为它是非可复制(切片会杀死多态)。

In Python you can get away with constructing/passing stuff on the fly because you are always dealing with references to reference-counted (and garbage-collected) objects . 在Python中,你可以逃脱构建/在飞行中通过的东西,因为你总是引用处理引用计数 (和垃圾收集的) 对象

The C++ object semantic is radically different - an object is an object, not a reference; C ++对象语义完全不同 - 对象对象,而不是引用; to obtain a semantic similar to Python's you would have to allocate every object dynamically with new and pass them around wrapped in shared_ptr<T> . 要获得类似于Python的语义,您必须使用new动态分配每个对象,并将它们传递给shared_ptr<T>

is it better in C++ to keep everything explicitly named 在C ++中保持所有显式命名是否更好

Not necessarily - it's perfectly normal to create temporaries, but you must be aware of what you can and cannot do with them, how references affect their lifetime, etc. 不一定 - 创造临时工作是完全正常的,但你必须知道你能做什么,不能做什么,参考如何影响他们的生命,等等。

I get the following error message from my compiler which explains it. 我从我的编译器收到以下错误消息,解释它。

std::ostream_iterator 's constructor takes a non const reference. std::ostream_iterator的构造函数采用非const引用。 There isn't a version of the constructor that takes a std::ofstream. 没有一个版本的构造函数采用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>]

In C++ we also often construct objects on-the-fly, but issues of ownership need to be minded. 在C ++中,我们还经常构建对象,但需要注意所有权问题。

The problem with ostream_iterator<int>(ofstream("my_file.txt")) is that a temporary object is getting passed to a constructor, but the constructed ostream_iterator object doesn't take ownership of the temporary's responsibilities. ostream_iterator<int>(ofstream("my_file.txt"))是临时对象传递给构造函数,但构造的ostream_iterator对象不承担临时ostream_iterator所有权。 If the ostream_iterator weren't also a temporary, it would continue to hold an invalid reference at the next line of code. 如果ostream_iterator也不是临时的,它将继续在下一行代码中保持无效引用。

There are ways around this, by passing to an identity function or by casting. 通过传递身份功能或通过强制转换,可以解决这个问题。 But they generally sacrifice safety, in the sense that if you use such a mechanism on a persistent variable it will create a dangling reference. 但是他们通常牺牲安全性,因为如果你在持久变量上使用这样的机制,它将创建一个悬空引用。

When you have several objects linked by references, without a container-contained relationship, current C++ best practice is to use named objects, not temporaries. 当你有几个通过引用链接的对象,没有容器包含的关系时,当前的C ++最佳实践是使用命名对象,而不是临时对象。

If you don't like this, you can choose to use shared pointers more often. 如果您不喜欢这样,您可以选择更频繁地使用共享指针。 That pattern allows the ownership to be shared between several references, with a container being hidden away. 该模式允许在多个引用之间共享所有权,并隐藏容器。 But that's not part of iostreams, and as design decision it would be a bit questionable here. 但这不是iostream的一部分,作为设计决定,这里有点可疑。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM