I understand no copy or assign for IO objects, so that we have to have reference sign & for istream/ostream objects. But why ifstream/ofstream or istringstream/ostringstream doesn't require a & to initialize an object? .
istream& input=cin;
ifstream infile;
infile("in");
istream needs a & and ifstream doesn't need a & to declare the variable.
Those two aren't really comparable; one has an initializer and the other doesn't.
But std::istream input = cin doesn't work because streams are not copyable. If you tried to initialize infile with an existing ifstream, you'd get the same error. Obviously, a reference entails no copying and so it works, aliasing the existing value.
Going the opposite way, if you leave out the initializer, then you can't have a reference because a reference requires an initializer. Instead, your stream will just default construct.
Related
void Employee::store_data(string filename) {
fstream file;
file.open(filename,ios::app | ios::binary);
if (file) {
file.write((char*)&this,sizeof(this));
file.close();
}
else cout<<"\n Error in Opening the file!";
}
this is what i tried.
I want to store the current object of employee class to a file in binary mode.
but i get this this
error: lvalue required as unary '&' operand
file.write((char*)&this,sizeof(this));
this isn't an actual variable, so you can't take its address. But it already is a pointer, so you don't need to. It also has size of a pointer, so your sizeof is wrong. And then in C++ you should not use C-style casts. So fixing these 3 things, your line becomes
file.write(reinterpret_cast<char*>(this), sizeof(*this));
That should compile.
However, note that if Employee contains anything complex, such as std::string member variables, pointer member variables, virtual methods, constructor / destructor etc, you can't read the data back. That write doesn't in that case write everything, or writes wrong runtime values, and you get garbage back. You enter the dreaded Undefined Behavior territory, anything can happen (including things apparently working when you test it).
The language does not allow use of &this as an expression since (https://timsong-cpp.github.io/cppwp/n3337/class.this#1)
the keyword this is a prvalue expression
You can use the addressof (&) operator only on lvalue expressions.
More importantly, you need to use
file.write(reinterpret_cast<char const*>(this), sizeof(*this));
to save the object.
Why are references to IO streams used instead of streams itself?And the same question about reference to the function.Trying to study this topic I still can't understand it.
In the code below function only prints result from the given QueryResult object on its given stream.
//declaration
ostream & print(ostream & os, const QueryResult &qr);
There is no "reference to function" here. The first & is part of the return type.
ostream& print(ostream& os, const QueryResult& qr);
The function returns a ostream& and takes a ostream& as parameter, because streams cannot be copied. The QueryResult is passed as constant reference to avoid a possibly expensive copy.
As you must know already that during function call arguments are copied to the function's parameters. But IO classes don't allow to copy their objects. Hence we cannot pass object(istream or ostream ) directly. or in simpler words
Because we can’t copy the IO types, we cannot have a parameter or return type that
is one of the stream types. Functions that do IO typically pass and
return the stream through references.
one more thing.
Reading or writing an IO object changes its state, so the reference must not be const
It is useful in method chaining. The aim is to return a fresh reference to a stream that can be passed along to the next call of operator<<() in the chain.
IO object can't be copied so we can't have return or parameter of IO type. So to do IO operation we must pass reference to the IO object to do cascading.
As the title says, I'm doing input validation in C++ (in this case, for an int). I'm using a stringstream object to getline from the user, using the stringstream to assign to a variable with the stream operator, like so:
if (sStream >> validInteger) {
if ((sStream >> input)) {
code code code
}
}
So in the first if statement, I'm getting the stringstream object I've created, and putting it into an integer type. If I use the stringstream to put a char into that integer type, the statement will return false and it won't actually assign to the integer, as expected in this situation.
I know that if you try to assign a char literal to an int with the assignment operator, it will just cast to the ASCII int value for that char (like int charInt = 'c' works fine and assigns the ASCII value)
So this means there is logic built into the sStream >> validInteger statement to not cast the data type, and to return false and to not actually assign the data to that variable.
My question is in regards to the logic for this statement. Where is this logic built in? Is the logic to return false and not assign within the stream operator (>>) or the stringstream object?
I've tested this with iostream and fstream objects like cin and ifstream, and they perform the same way. But is this logic built into cin and fstream as well? Or is it just in the stream operator (>>)?
My code is functional and everything works as expected, I just wanted to clarify how C++ operators/objects actually work in this case for my own knowledge.
To elaborate, you can always check cppreference. At the top of stringstream you can see the inheritance tree, and compare with other input streams to see the first shared ancestor. Then, look at it:
The istream::operator>> states
(1) arithmetic types
Extracts and parses characters sequentially from the stream to interpret them as the representation of a value of the proper type,
which is stored as the value of val.
Internally, the function accesses the input sequence by first constructing a sentry object (with noskipws set to false). Then (if
good), it calls num_get::get (using the stream's selected locale) to
perform both the extraction and the parsing operations, adjusting the
stream's internal state flags accordingly. Finally, it destroys the
sentry object before returning.
so quite a bit under the hood. A proper type checking is implemented.
The operation:
sStream >> validInteger
returns the stream object, not true, false or some error. The state of the the stream object (or any other stream object types in the iostream library) can be converted to something that can be tested with an if(), or other conditional construct, via an operator overload of the void * conversion in earlier versions of C++, and a bool conversion in the latest versions.
Can some lovely soul help me out with this one :)
Could you please explain each piece of this line of code
and what each Individual piece does? Thank you in advance.
istream & operator >>( istream & input, Registration & R )
ostream & operator <<( ostream & os, const Registration & R )
istream & operator >>( istream & input, Registration & R )
istream& means that object of type istream will be returned by reference.
operator>> is the identifier of the function, it is specifically named so that it overrides the default functionality of the >> operator (similar to how you can override the default functionality the + operator, or operator+() as a "binary" (meaning two) operator (meaning it involves two arguments).
(...) everything within the parentheses are the parameters of the function, they are the data that will be given to the function when it is called to be run.
istream& input indicates that a variable called "input" of type istream will be passed in by reference, meaning that usage of the input variable will refer to the original variable passed in from the location in which it was called and NOT a copy (see: passing by reference and passing by value).
Registration& R indicates that a variable called "R" of type Registration will be passed in by reference (see the definition above). The type Registration seems to be derived from some method for defining a type, such as from a class or a struct.
If you're looking for more information on what an object of type istream is, how it's defined, or what "it does," (along with anything else I mentioned here) I recommend running a search and looking through the wealth of free, available information online.
Having
int a;
in C++, why doesn't
cin >> a;
need ampersand like
scanf("%d", &a);
in C ?
In C++, we have not only variables and pointers (as in C), but also references. On the calling side, passing a reference looks like passing a variable by value, but on the side of the function called, it actually receives not a copy, but a reference to the actual variable and hence can alter it. You can think of a reference like a pointer but without the need to de-reference.
std::istream& operator>> (std::istream&i, some_type&x);
declares an operator that takes a reference to a std::istream and another to some_type and returns the std::istream reference. With this declaration you can now
some_type x;
std::cin >> x; // calls above operator, pasing x by reference
Passing by reference and passing by pointer are very similar, and may actually produce identical code:
void f1(int*x) { *x=2; }
void f2(int&x) { x=2; }
int a;
f1(&a); // is equivalent
f2(a); // to this
The common wisdom in C++ is to pass variables that shall not be altered either by value (if they fit into a single register) or by const reference. Variables that may be altered by the function called can either be passed by (non-const) reference or by pointer, this is a matter of style: with the latter it is explicit at function call that the variable can be altered, while the former (passing by reference) requires one to look up the API of the function to find out whether one passes by value, reference, or const reference.
cin and i are passed by reference to operator >> given it the ability to read and write cin and i.
As C has no true reference passing, scanf("%d", &a); code needs to pass the address of a for scanf() to write a value to a.
C and C++ use fundamentally different methods when passing arguments of varying type.
In C, a single function like scanf(const char* pattern, ...) can accept many different types of parameters. That's why it needs a pattern parameter where you tell it the actual types it has received. If you pass anything unexpected, you have a runtime issue.
In C++, a single function name may be implemented repeatedly for different types of parameters. This is called overloading. Each overloaded implementation will know exactly what it expects, and the compiler will assure that it only gets that type of values. If there's no matching overload, you have a compile-time error.
Another difference is that in C++, cin >> i is actually a function call of operator>>. In C, function calls all look like functionName(argument)
You can use scanf in c++ , How ever still better to use cin. "cin>>"not "cin<<"
#include <iostream>
#include <stdio.h>
using namespace std;
int main(){
float x;
scanf("%f",&x);
printf("%.1f",x);
return 0;
}