Here is my problem:
int addsomeStuff(std::ostream &cout, int b) {
cout << b;
return 2;
}
int main() {
int a = 1;
cout << a << addsomeStuff(cout, 3) << endl;
return 0;
}
Output: 312
Can Someone explain me the Output, i would expect the output more like 132
why is the compiler runs first the Function before making the operator.
How i run into this issue:
I have a container class which can hold data inside an bytearray.
Somehow the 'container.WriteConvert(..);' get inserted into bytearray before the integer called 'a'. Does anyone have an explaintation for that.
I could make the WriteConvert static or add an extra Line which would fix this problem, instead of returning an Container& but i am kinda intrested whats the reason the Compiler puts this in this order.
int a = 2;
Container container;
container << a << container.WriteConvert("TestString");
int b = 0;
container >> b;
cout << b;
// The ouput of 'b' is some stupid Data which is caused by WriteConvert.
The Reason i didnt wrote this WriteConvert static or outside of the Container class has some reason. I have also ReadConvert which i dont want to have multiline. If someone has another idea i am open for other solutions, without increasing line amount.
int b = 0;
string output
container >> b >> container.ReadConvert(output);
cout << b;
Pre C++17, the order of evaluation of the chained operator arguments' was unspecified. That means the execution could've first evaluated addsomeStuff(cout, 3) call (thus printing 3 first) and then proceed to print a and the returned value of addsomeStuff(cout, 3).
With C++17, the order of evaluation is well defined - left to right. That means that if your compiler correctly implements the C++17 standard, the only possible output is 132.
If you are stuck with a pre C++17 standard, you would need to first evaluate all the arguments and then use them in chained operator call or don't use chained operator calls:
int main() {
int a = 1;
cout << a;
cout << addsomeStuff(cout, 3) << endl;
return 0;
}
The former approach may alter the behaviour, but will be well-defined.
Related
This question already has answers here:
Order of evaluation in C++ function parameters
(6 answers)
Warn about UB in argument evaluation order
(1 answer)
Closed 2 years ago.
I'm new at programming. This is part of my code:
double logic(double a,double b)
{
(Code Here...)
}
double inputDouble(double x)
{
std::cout << "Please, input a floating number: ";
std::cin >> x;
std::cout << std::endl;
return x;
}
int main()
{
double a,b;
std::cout << logic(inputDouble(a),inputDouble(b));
return 0;
}
I've noticed the problem on the compiler, them I've checked the debug windows and the problem that I'm having is that when I insert a value on 'a' by 'inputDouble' function, it goes to 'b', and vice-versa. So at the end of the program what I get in 'logic' function is: double a=b(From main()), double b=a(From main()). I hope and am grateful to someone who can explain to me what I'm doing wrong so the variables are being assigned on the wrong places. And I also apologize if there is any gramatical mistake on this post as english is not my first language.
The expression:
logic(inputDouble(a),inputDouble(b))
does not guarantee the order in which those calls to inputDouble() are made, just that they're both complete before the call to logic(). So it may call the a one first, or it may call the b one first(a).
To guarantee order, you can use something like:
double inputDouble() { // slight change, see below.
double x;
std::cout << "Please, input a floating number: ";
std::cin >> x;
std::cout << std::endl;
return x;
}
int main() {
double a = inputDouble(); // guarantee get 'a' first.
double b = inputDouble();
std::cout << logic(a, b);
return 0;
}
You could also use:
double a = inputDouble(); // guarantee get 'a' first.
std::cout << logic(a, inputDouble());
but I prefer the first one for consistency.
You'll notice a slight change to the inputDouble() function as well to remove the parameter, no useful purpose is served by passing the uninitialised values to the function, then over-writing and returning it.
Instead, I've just used a local variable to receive the value and return it.
A more robust program would also ensure that user input was valid but that can be left for a different question, since it almost certainly already exists on this site.
(a) For the language lawyers amongst us, this is covered in C++20 [expr.call] /8 (my emphasis):
The initialization of a parameter, including every associated value computation and side effect, is indeterminately sequenced with respect to that of any other parameter. [Note: All side effects of argument evaluations are sequenced before the function is entered].
I try to make an array and take input and then simply showing the output on the screen but uses classes and objects, Here is my code:
#include<iostream>
using namespace std;
class array{
int ar[], n;
public:
void input();
int display();
}obj;
void array::input(){
cout<<"Enter item size: ";
cin>>n;
int ar[n]={};
for(int i=0; i<n; i++){
cout<<"Enter value at index "<<i<<" : ";
cin>>ar[i];
}
}
int array::display(){
cout<<"You Entered: ";
for(int i=0 ; i<n; i++){
cout<<ar[i];
}
}
int main(){
obj.input();
obj.display();
}
In the sample run, I entered 1 and 2 and I am expected to get 1 and 2.
Two problems in your code.
First int ar[] should not compile. I get the following error:
prog.cc:4:12: error: ISO C++ forbids flexible array member 'ar' [-Wpedantic]
int ar[], n;
^
Next, in array::input() you create a completely new array int ar[n]={}; which is also not valid c++. Array sizes must be compiletime constants. Moreover, this array shadows the member and is unrelated to it (apart from having the same name). So this ar is gone once you return from the method. You never write anything into the member ar.
If you dont know the size in advance you should use a std::vector:
#include <iostream>
#include <vector>
class array{
std::vector<int> ar;
public:
void input();
int display();
};
void array::input(){
std::cout << "Enter item size: ";
int n;
std::cin >> n;
ar.resize(n);
for(int i=0; i<n; ++i){
std::cout << "Enter value at index " << i << " : ";
std::cin >> ar[i];
}
}
int array::display(){
std::cout<<"You Entered: ";
for(int i=0 ; i<n; ++i){
std::cout << ar[i];
}
}
int main() {
array obj;
obj.input();
obj.display();
}
PS: read here why using namespace std; is bad practice: Why is "using namespace std" considered bad practice?
IMHO user463035818s answer is sufficient, but for all that OP asked me
how to fix this compiler issue.
The recommended fix would be by design i.e. like shown in user463035818s answer.
So, I want to elaborate how to fix the sample code of OP (with "minimal" changes). That might make obvious why user463035818s answer is the better one. (I repeated the link three times – it should be clear to everybody that I consider this as the better solution.)
The actual compiler error (or warning or feature accepted by compiler extension):
OP used int ar[] a C array as class member without denoting the size.
This is called Flexible array member but it is a C99 feature (not supported by the C++ standard).
The linked Wikipedia article provides a nice example:
struct vectord {
size_t len;
double arr[]; // the flexible array member must be last
};
To be clear, flexible array members don't provide automatic allocation. They just represent an array of arbitrary length. The programmer is responsible to grant sufficient storage for that array. Hence even in C, and with the resp. syntax adjustments, this code would have been broken.
Some C++ compilers adopt features from C as (proprietary) extension. That's the reason that OP got responses ranging from "On my side, it works."1 to "This is a compiler error." However, I would consider usage of such extensions as bad style in general. With different compiler settings or a different compiler, this might not work anymore.
1 This is not the only issue of OPs code. "It works" might be merely bad luck. OPs code has Undefined Behavior. One kind of Undefined Behavior is "It works" which is not the best one because programmer might believe that the code is fine.
A lot of higher level languages (Java, C#, Python) tries to cover memory allocation and storage management "under the hood" completely because it's not quite easy to make this always correct and consider every edge case sufficiently. This might cause an additional performance impact for the administration of memory. In C and C++, the programmer has ful control over memory allocation. It's both a blessing and a curse.
The standard library of C++ provides a variety of tools to make programmers allocation life easier.
For dynamic arrays, the tool of choice is the template class std::vector. It provides an overloaded operator[] which allows that it can be accessed just like an array. It provides methods like reserve() and resize(). The storage is internally managed.
I would strongly recommend to use std::vector but there is also the possibility to do it using new[] and delete[].
For this, the class array might look as follows:
class array {
int *ar; // a raw pointer for storage
int n; // the current size of array
public:
int display();
int* and int are plain old data types → implicit construction leaving them uninitialized. So, there really should be defined at least a default constructor.
array(): ar(nullptr), n(0) { }
The input() method has to ensure proper storage.
void input()
{
// release old memory (if there is one)
delete[] ar; ar = nullptr; n = 0;
// input
std::cout << "Enter item size: ";
std::cin >> n;
if (n <= 0) return;
ar = new int[n];
for (int i = 0; i < n; ++i) {
std::cout << "Enter value at index " << i << ": ";
std::cin >> ar[i];
}
}
When an instance of class array is deleted it should release the internal storage. Otherwise, the allocated memory pointed by ar will be orphaned and lost until process is terminated by OS. Such lost memory is called memory leak.
~array() { delete[] ar; }
Please, note that calling delete[] (or delete) with a nullptr is valid. Hence, no extra if (ar) is needed.
Finally, we have to obey the Rule of three. The compiler generates implicitly copy constructor and copy assignment operator which will copy the class array members by value. Copying a pointer by value does not mean that the contents (it points to) is copied. It just means copy the pointer (address value). Hence, an (accidental, unintended) copy of class array could result in two instances of class array which members ar point to the same memory. Once, one of them deletes that memory, the ar of the other becomes dangling i.e. points to released memory. (Bad!) If the other instance is destroyed also it will delete[] ar again. This is double deleting which is prohibited. (Bad again!)
One option could be to define copy constructor and copy assignment to handle this appropriately by making a deep copy of ar contents (with another new[]). However, if copy is not intended, an alternative is to just explixitly prohibit copy for class array:
array(const array&) = delete;
array& operator=(const array&) = delete;
};
Putting this althogether in array.cc:
#include <iostream>
class array {
int *ar; // a raw pointer for storage
int n; // the current size of array
public:
array(): ar(nullptr), n(0) { }
~array() { delete[] ar; }
array(const array&) = delete;
array& operator=(const array&) = delete;
void input();
void display();
};
void array::input()
{
// release old memory (if there is one)
delete[] ar; ar = nullptr; n = 0;
// input
std::cout << "Enter item size: ";
std::cin >> n;
if (n <= 0) return;
ar = new int[n];
for (int i = 0; i < n; ++i) {
std::cout << "Enter value at index " << i << ": ";
std::cin >> ar[i];
}
}
void array::display()
{
std::cout << "You Entered: ";
for (int i = 0; i < n; ++i) {
std::cout << ar[i];
}
std::cout << '\n';
}
int main()
{
array obj;
obj.input();
obj.display();
return 0;
}
Compiled and tested:
$ g++ -std=c++11 -Wall -pedantic array.cc && ./a.out
Enter item size: 1↲
Enter value at index 0: 2↲
You Entered: 2
$
Live Demo on coliru
The last sentence in OPs question is a bit unclear for me (although I assume it's just bad worded):
In the sample run, I entered 1 and 2 and I am expected to get 1 and 2.
Either input is 2 1 2 then output is 1 2.
Or input is 1 2 then output is 2.
Please note that array::input() expects first input of array::n but array::display() doesn't output array::n.
I am trying to return values (namely rows and columns) upon a file read, and since I will be reading in multiple files and getting the same variables from each file, I thought it will be better for me to write a function rather than copying and pasting duplicate codes.
Anyway, I am trying to return 2 values and to use them too, please see my code below:
#include <iostream>
#include <fstream>
using namespace std;
int r(string fn);
int main()
{
int a, b = r("input_a.txt");
cout << "a --- " << a << endl;
cout << "b --- " << b << endl;
}
int r(string fn)
{
ifstream fin01;
string file = fn;
fin01.open(file.c_str());
...
...
...
// Suppose I should be getting 2 for 'rows' and 3 for 'cols'
return rows, cols;
}
I got 0x7fff670778ec and 0x7fff670778e8 for my output instead...
Any pointers?
You cannot return two values from a function that is declared to have a single int as return type:
int r(string fn){
/*...*/
return rows,cols; // <-- this is not correct
}
Also the way you call this function is not behaving as you might expect:
int a, b = r("input_a.txt");
this declares two integers and initializes the second one with the return value of the function, but the first one stays uninitialized (see TerraPass answer for more explanation on the comma operator).
You basically have two options. First option is to pass references to the function and the function assigns the results to those references:
void r(string fn, int& rows,int& cols) {
/*...*/
rows = x;
cols = y;
}
and you call it like this:
int a,b;
r("someString",a,b);
However, in this way the caller has to "prepare" those return values. Imho it is more convenient to use the return value to return results from a function (sounds logical, no?). To do this you just have to define a type that encapsulates the two integers:
struct RowAndCol { int row;int col; };
RowAndCol r(string fn) {
/*...*/
RowAndCol result;
result.row = x;
result.col = y;
return result;
}
and call it like this:
RowAndCol rc = r("someString");
Note that you could also use a std::pair<int,int> instead of defining your custom struct (see e.g. molbdnilos answer). However, IMHO whenever you know exactly what is contained in the pair, it is better to give it a reasonable name (e.g. RowAndCol) instead of using a naked std::pair<int,int>. This will also help you in case you need to add more methods to the struct later (e.g you might want to overload the std::ostream& operator<< for your struct to print it on the screen).
PS: Actually your output does not look like it was produced by the code you are showing. Theses are some memory addresses, but in your code there is neither a pointer nor an address-of operator.
I guess you're used to Python (I peeked at your profile), but the comma does not create a pair in C++.
(You may not have thought about it that way, but you can only return one value from a Python function, too. If you "return two values", you're returning one pair.)
Fortunately, there are tuples in the standard library.
#include <iostream>
#include <fstream>
#include <utility>
std::pair<int,int> r(std::string fn);
int main()
{
std::pair<int, int> result = r("input_a.txt");
cout << "a --- " << result.first << endl;
cout << "b --- " << result.second << endl;
// Or,
int a = 0;
int b = 0;
std::tie(a, b) = r("input_a.txt");
cout << "a --- " << a << endl;
cout << "b --- " << b << endl;
}
std::pair<int, int> r(std::string fn)
{
std::ifstream fin01(fn);
// ...
return std::make_pair(rows, cols);
}
Functions in C++ cannot return multiple values of their return type via a return statement.
int a, b = r("input_a.txt");
...
return rows, cols;
These 2 lines don't do what you think they do.
The line int a, b = r("input_a.txt"); is equivalent to:
int a;
int b = r("input_a.txt");
That is, you declare variables a and b and initialize b to the return value of r("input_a.txt"), while a remains uninitialized.
The line return rows, cols; is equivalent to:
rows;
return cols;
...and is an example of comma operator, which evaluates its left operand (in your case, rows), discards the result, then evaluates its right operand (in your case, cols) and returns the result of this evaluation. So, in effect, your function r(), as it is now, always returns a single value, cols.
If you need to return more than one value from a function, you should consider accepting additional arguments as non-const references for you to store resulting values to, or changing the return type of your function to some struct, which would contain all of the values you want to return. You can find an example of both these approaches in #tobi303's answer.
This question already has answers here:
Order of evaluation of arguments using std::cout
(5 answers)
Closed 1 year ago.
I'm learning c++, and recently run into a confusing problem, here's the code:
#include <iostream>
using namespace std;
class A {
public:
A() { a[0] = 1; a[1] = 0; }
int a[2];
int b(void) { int x=a[0];a[0]=a[1];a[1]=x; return x; }
};
int main(void) {
A a;
cout<<a.a[0]<<a.a[1]<<endl; //outputs 10
a.b();
cout<<a.a[0]<<a.a[1]<<endl; //outputs 01
a.b();
cout<<a.a[0]<<a.a[1]<<endl; //outputs 10
cout << a.b() << //outputs 1
endl<< a.a[0]<<a.a[1] << endl; //outputs 10???
cout<<a.a[0]<<a.a[1]<<endl; //outputs 01???
return 0;
}
The first two calls of b() behaves as expected, but when i call b() within the cout statement, it doesn't switch the two elements of the array right away, but later i check it, it's already switched.
Can you help me understand this behavior? Thank you.
std::cout << f() << g();
The order of evaluation of the two function calls is unspecified; the compiler can call g() then f(), or it can call f() then g().
Same thing in your code; the compiler can squirrel away the value of a.a[0] the call a.b(), or it can call a.b() then grab the value of a.a[0].
Function evaluation in an expression depends on compiler stream operations such as << and >>. The same problem that happens when you evaluate x = f1() + f2(). You don't know which will be evaluated first because it's compiler dependent.
It would be more safe to call these on separate lines to rule out the ambiguity.
I have the following sample code. Just wanted to know if is valid to take address of a local variable in a global pointer and then modify it's contents in a sub function. Following program correctly modifies value of variable a . Can such practice cause any issues ?
#include <iostream>
#include <vector>
using namespace std;
vector<int*> va;
void func()
{
int b ;
b = 10;
int * c = va[0];
cout << "VALUE OF C=" << *c << endl;
*c = 20;
cout << "VALUE OF C=" << *c << endl;
}
int main()
{
int a;
a = 1;
va.push_back(&a);
func();
cout << "VALUE IS= " << a << endl;
return 0;
}
This is OK, as long as you don't try to dereference va[0] after a has gone out of scope. You don't, so technically this code is fine.
That said, this whole approach may not be such a good idea because it makes code very hard to maintain.
I'd say that if your program grows you could forget about a change you made in some function and get some weird errors you didn't expect.
Your code is perfectly valid as long as you call func() while being in the scope of a. However, this is not considered to be a good practice. Consider
struct HugeStruct {
int a;
};
std::vector<HugeStruct*> va;
void print_va()
{
for (size_t i = 0; i < va.size(); i++)
std::cout<<va[i].a<<' ';
std::cout<<std:endl;
}
int main()
{
for (int i = 0; i < 4; i++) {
HugeStruct hs = {i};
va.push_back(&hs);
}
print_va(); // oups ...
}
There are 2 problems in the code above.
Don't use global variables unless absolutely necessary. Global variables violate encapsulation and may cause overlay of variable names. In most cases it's much easier to pass them to functions when needed.
The vector of pointers in this code looks awful. As you can see, I forgot that pointers became invalid as soon as I left for-loop, and print_va just printed out garbage. The simple solution could be to store objects in a vector instead of pointers. But what if I don't want HugeStruct objects to be copied again and again? It can take quite a lot of time. (Suppose that instead of one int we have a vector of million integers.) One of the solutions is to allocate HugeStructs dynamically and use vector of smart pointers: std::vector<std::shared_ptr<HugeStruct>>. This way you don't have to bother about memory management and scope. Objects will be destroyed as soon as nobody will refer to them.