ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
Hi All,
Since everyone was so helpful last time i figured i would try you for another question.
In java if i want to return an input stream i could just do something like this.
Code:
FileReader openFile( String path ){
return new FileReader(path);
}
Now, im going for something similar in c++. I know that c++ would actually try to return a copy of the ifstream instead of the object refrence which is what im going for. What i tried is.
Code:
ifstream& openFile ( char str[] );
ifstream& openFile ( char str[] )
{
ifstream inFile;
inFile.open(str);
return inFile&;
}
int main()
{
//Some random code to give str an actual value.
ifstream inFile = openFile(str);
return 0;
}
However, i cant get it to compile. Is my thought process on how to return a refrence to my ifstream correct?
Is my thought process on how to return a refrence to my ifstream correct?
No you have an ampersand added to the ifstream which makes no sense in this situation and you can not return a reference to an instance which will go out of scope. If this was a constant reference then the life of the temporary would be extended but also become useless as it would be constant.
What exactly do you think this function gains you?
streams use RAII so your code could be written like
Code:
int main()
{
//Some random code to give str an actual value.
std::ifstream inFile(str);
}
Last edited by Biddle; 03-25-2009 at 09:22 PM.
Reason: added link
In java if i want to return an input stream i could just
Java has a garbage collector, so it can use references the way C++ uses pointers without worrying about who does the delete.
In C++ if you want a function to return an object it allocated, the only direct approach is to return a pointer, not a reference.
Then the caller becomes responsible for ultimately deleting the object.
In many kinds of programming it is possible and worthwhile to have a much more structured relationship between the creation point of an object and its deletion point. Then it would be a violation of that structure to return a pointer to the function allocated object, so you're not left with good choices.
In other kinds of programming, you just recognize that object ownership issues are consistently part of the problem so you must be consistently careful with their solution.
I don't know the style nor structure of your project. So one answer is return by pointer and remember to delete later. But that may not be a good answer.
A better way to do it is to take a reference to std::ifstream, modify it, and return bool to indicate the result. Returning a new object comparably to the way Java does is often done with std::auto_ptr; however, that's a borderline-useless class because you can't even create a list of std::auto_ptr. If you're actually initializing an object with the return, you can return it by value and initialize with e.g. ifstream inFile( openFile(str) );, which will generally prevent copying the object because inFile in main is constructed where inFile in openFile was at the time openFile returns. These things are what Java hides from you; in reality, Java just creates a pointer to a new object wrapped with a shared pointer. For everything, except maybe integral types. That should generally be avoided in C++, especially when you know what you need at compile time (as is the case here.)
Kevin P. Barry
PS This looks like I'm responding to the others here, also; however, it just took me a long time to write my response and by the time I posted it, others had, also.
I find it hard to believe people are suggesting heap allocation or using a construct in place, when the stream object does not have a copy constructor as it makes no sense. Which copy would own the resource, which one should close it?
I find it hard to believe people are suggesting heap allocation
What's the problem with heap allocation?
Quote:
or using a construct in place, when the stream object does not have a copy constructor
I've never had a good understanding of the rules in the standard for that one:
Object 1 is in local scope in a function. The function returns that object by value implying temporary object 2 created by copy constructor from object 1. That temporary is the input to the constructor of object 3, so a second call to the copy constructor copying 2 to 3?
Sometimes the compiler figures out to short circuit those two copy constructors and do it all with one object. When (if ever) must the compiler short circuit those copy constructors? When (if ever) may the compiler short circuit those copy constructors? If must doesn't equal may, that makes a very confusing features. If they do equal then the examples I've looked at are very confusing and/or compiler bugs. Either way, this is a construct I'd rather not use at all with any object with interesting construction.
I find it hard to believe people are suggesting heap allocation or using a construct in place, when the stream object does not have a copy constructor as it makes no sense. Which copy would own the resource, which one should close it?
Yes, I don't often use std::ifstream so I forgot about the copy constructor. However, you're incorrect saying that it doesn't have one; it has one, but it's private. If it was public, however, it wouldn't be called with construct-in-place. The visibility alone causes it to fail.
Code:
//(compile with '-O0' just to make sure)
#include <stdio.h>
struct myclass
{
myclass()
{ fprintf(stderr, "construct\n"); }
~myclass()
{ fprintf(stderr, "destruct\n"); }
//make this 'private' and it won't compile, but it's never called
myclass(const myclass&)
{ fprintf(stderr, "copy\n"); }
};
myclass copy_me()
{
myclass temp;
return temp;
}
int main()
{
myclass one( copy_me() );
}
In this case, there should be no ambiguity about resources if no copy is made. In my own classes, I'd rather make a copy without resources than make a copy fail entirely. For example, when I write copy constructors for classes with mutexes, I initialize a new mutex in the lvalue but copy the remaining salient information. It wouldn't make sense to prevent copying of such an object. In OP's case, it would make perfect sense for std::ifstream to reopen the file in the lvalue, then close the file in the rvalue when it destructs; they won't interfere with each other if it does a dup and fdopen internally (inefficiency aside, that's very logical behavior.) The "problem" here is that standard C++ is for all systems; therefore, the lowest common denominator is to require that std::ifstream not be copyable.
What if someone wants a list of std::ifstream? Does it make sense to prevent that versatility because "somebody" (not you; the unspecified somebody) doesn't know what to do when something with resources is copied? The answer to the question of resources is as clear here as it is with dynamic memory (at least in the context of POSIX.) Shared memory, threads, mutexes, conditions, etc. are cases where it isn't as clear, but it isn't unreasonable to copy everything within a class except for those things; all one has to do is document the behavior.
Kevin Barry
PS This is one of the many reasons I always use C for I/O (except in OS-portable libraries.)
Well what does it gain in this instance? It extends the life of the temporary yes but it also introduces the possibility of a memory leak, when the class is intentionally designed to release resources on going out of scope. In addition the OP's code can be completed in a one liner, yet instead it is reimplementing the constructor.
Quote:
Sometimes the compiler figures out to short circuit those two copy constructors and do it all with one object. When (if ever) must the compiler short circuit those copy constructors? When (if ever) may the compiler short circuit those copy constructors?
Quote:
12.8
Whenever a temporary object is copied using a copy constructor, and this object and the copy have the same cv-unqualified type, an implementation is permitted to treat the original and the copy as two different ways of referring to the same object and not perform a copy at all, even if the copy constructor or destructor have side effects.
Note that as ta0kira pointed out and I meant to say (it was 3 am )
Quote:
A program is ill-formed if the copy constructor or the copy assignment operator for an object is implicitly used and the special member function is not accessible (clause 11).
Quote:
In this case, there should be no ambiguity about resources if no copy is made.
Yes but whether a copy is made is up to the implementation therefore it may or may not happen.
Quote:
In OP's case, it would make perfect sense for std::ifstream to reopen the file in the lvalue, then close the file in the rvalue when it destructs; they won't interfere with each other if it does a dup and fdopen internally (inefficiency aside, that's very logical behavior.) The "problem" here is that standard C++ is for all systems; therefore, the lowest common denominator is to require that std::ifstream not be copyable.
Just look at why the stream does not make available the copy constructor, they share global state. A stream is constructed and some data is written to it, then the stream is copied to another. Does the second stream share the same global state of the offsets that the first has? ie should reading from the second state start at offset zero or the first streams offset. Also look at writting to the stream.
I assumed the original post represented a greatly simplified example of what Fredstar actually wants to do.
In that example, there is no benefit to having the openFile function at all, vs. opening the file in the main function.
If the real code adds something that provides a reason to open the file in that function, then using the heap to allocate the ifstream object and returning it by pointer is the simple way to avoid significantly restructuring the code.
Just look at why the stream does not make available the copy constructor, they share global state. A stream is constructed and some data is written to it, then the stream is copied to another. Does the second stream share the same global state of the offsets that the first has? ie should reading from the second state start at offset zero or the first streams offset. Also look at writting to the stream.
That's perfectly reasonable behavior (error checking and mode aside.) I use this pattern quite a bit to allow me to tabulate objects that use IPC, although 99% of the time the copy is made with a NULL file and I change it in place.
Kevin Barry
Again, if others will use it, all you need to do is document your solutions to ambiguity, e.g. buffering mode, stream position, etc.
Sorry it has been so long since i was able to check in on this thread.
I want to say thanks to everyone for your input. I'm really new to c++ and have some bad habits, or just a few things i got really used to in java that i wont be able to do in c++.
Yes, the above post was a "very" slimmed version of what i was trying to do but realised that in c++ i could just pass reference to an already opened ifstream.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.