How does the program 'remember' the temporary object? - c++

#include <iostream>
using namespace std;
class A {
public:
int first;
int last;
A(int x = 0, int y = 0):first(x), last(y){}
A(A&a) { cout << "c ctor \n"; }
};
ostream& operator<<(ostream& os, A b) {
os << "first:" << b.first << " last:" << b.last << endl;
return os;
}
istream& operator>>(istream& is, A a) {
is >> a.first >> a.last;
return is;
}
int main()
{
A i;
cout << "enter first and last: \n";
cin >> i;
cout << i;
system("pause");
return 0;
}
A a is a new A object in the >> overload, and if we enter 6 4 into it, the program will remember it in the << overload function, and print what we entered into it. Can someone explain why? Thanks.

This is a wrong statement relative to your presented code because the operator >> deals with a copy of the original object used as an argument of the operator.
The operator should be declared like
istream& operator>>(istream& is, A &a) {
is >> a.first >> a.last;
return is;
}
And moreover the copy constructor does not copies data members.
So the program has undefined behavior. For example running it using clang HEAD 11.0.0 you can get the following result
prog.cc:8:9: warning: unused parameter 'a' [-Wunused-parameter]
A(A&a) { cout << "c ctor \n"; }
^
1 warning generated.
enter first and last:
c ctor
c ctor
first:4202496 last:0
That is the program outputs the variables first and last with indeterminate values because the data members of the created object b in the operator << were not initialized.

Related

Overloading the assignment operator= doesn't work for anything except the implicit object passed in c++

The comparison in the assignment operator works as expected, but when I try to use a temp variable and load then return that, all it returns is the defaults. Debugs show that the values are default 1 x 4, but I'm not sure what to with it to make it fill the temp variables and return them. Everything I've gone through says it should work.
Debug info:
- poly {coefficient="2" variable="x" exponent="4" } Polynomial
+ coefficient "2" std::string
+ variable "x" std::string
+ exponent "4" std::string
- poly2 {coefficient="3" variable="x" exponent="4" } Polynomial
+ coefficient "3" std::string
+ variable "x" std::string
+ exponent "4" std::string
- poly3 {coefficient="1" variable="x" exponent="4" } Polynomial
+ coefficient "1" std::string
+ variable "x" std::string
+ exponent "4" std::string
main
// Demonstrating class Polynomial's overloaded stream insertion
// and stream extraction operators.
#include <iostream>
#include "Polynomial.h"
using namespace std;
int main() {
Polynomial poly; // create object poly
Polynomial poly2; // create object poly
Polynomial poly3; // create object poly
Polynomial poly4; // create object poly
Polynomial poly5; // create object poly
cout << "Enter polynomial number in the form 2x4:" << endl;
// cin >> phone invokes operator>> by implicitly issuing
// the non-member function call operator>>(cin, phone)
cin >> poly;
cout << "\nThe polynomial number entered was:\n";
// cout << phone invokes operator<< by implicitly issuing
// the non-member function call operator<<(cout, phone)
cout << poly << endl;
cout << "Enter polynomial number in the form 2x4:" << endl;
// cin >> phone invokes operator>> by implicitly issuing
// the non-member function call operator>>(cin, phone)
cin >> poly2;
cout << "\nThe polynomial number entered was:\n";
// cout << phone invokes operator<< by implicitly issuing
// the non-member function call operator<<(cout, phone)
cout << "poly2 " << poly2 << endl;
poly3 = poly + poly2;
cout << "poly3 " << poly3 << endl;
poly4 = poly - poly2;
cout << "poly4 " << poly4 << endl;
poly5 = poly;
cout << "poly5 " << poly5 << endl;
}
Header
#pragma once
#ifndef POLYNOMIAL_H
#define POLYNOMIAL_H
#include <iostream>
#include <string>
class Polynomial {
friend std::ostream& operator<<(std::ostream&, const Polynomial&);
friend std::istream& operator>>(std::istream&, Polynomial&);
public:
// Default Constructor
Polynomial(std::string coefficient = "1", std::string variable = "x",
std::string exponent = "4");
// Copy Constructor
Polynomial(const Polynomial& copy)
: coefficient{ copy.coefficient }, variable{ copy.variable },
exponent{ copy.exponent } {
std::cout << "Copy Constructor called" << std::endl;
}
void setPolynomial(std::string, std::string, std::string);
Polynomial getPolynomial();
// addition operator; Polynomial + Polynomial
Polynomial operator+(const Polynomial&) const;
// subtraction operator; Polynomial - Polynomial
Polynomial operator-(const Polynomial&) const;
// assigment operator; Polynomial - Polynomial
Polynomial operator=( Polynomial&);
private:
std::string coefficient; //
std::string variable; //
std::string exponent; //
};
#endif
Polynomial.cpp
// Overloaded stream insertion and stream extraction operators
// for class PhoneNumber.
#include "Polynomial.h"
#include <iomanip>
using namespace std;
// default constructor; conversion constructor that converts
Polynomial::Polynomial(std::string co, std::string va, std::string ex) {}
// Setters
void Polynomial::setPolynomial(std::string co, std::string va, std::string ex) {
this->coefficient = co;
this->variable = va;
this->exponent = ex;
}
// Getters
Polynomial Polynomial::getPolynomial() { return *this; }
// overloaded stream insertion operator; cannot be a member function
// if we would like to invoke it with cout << somePhoneNumber;
ostream& operator<<(ostream& output, const Polynomial& number) {
output << "Coefficient: " << number.coefficient
<< "\nVariable: " << number.variable
<< "\nExponent: " << number.exponent << "\n"
<< "" << number.coefficient << "" << number.variable << "^"
<< number.exponent << "\n";
return output; // enables cout << a << b << c;
}
// overloaded stream extraction operator; cannot be a member function
// if we would like to invoke it with cin >> somePhoneNumber;
istream& operator>>(istream& input, Polynomial& number) {
input >> setw(1) >> number.coefficient; // input area code
input >> setw(1) >> number.variable; // input exchange
input >> setw(1) >> number.exponent; // input line
return input; // enables cin >> a >> b >> c;
}
// addition operator; Polynomial + Polynomial
// A member function takes an implicit first parameter
Polynomial Polynomial::operator+(const Polynomial& op1) const {
Polynomial temp; // temporary result
if (this->variable == op1.variable) {
if (this->exponent == op1.exponent) {
// Use stoi string to int
int num1 = stoi(this->coefficient);
int num2 = stoi(op1.coefficient);
// use to_string to set coefficient
std::string s = std::to_string(num1 + num2);
temp.coefficient = s;
temp.variable = this->variable;
temp.exponent = this->exponent;
}
else {
std::cout << "Exponents must match\n";
}
}
else {
std::cout << "Variables must match\n";
}
return temp; // return copy of temporary object
}
// substraction operator; Polynomial - Polynomial
// A member function takes an implicit first parameter
Polynomial Polynomial::operator-(const Polynomial& op1) const {
Polynomial temp; // temporary result
if (this->variable == op1.variable) {
if (this->exponent == op1.exponent) {
// Use stoi string to int
int num1 = stoi(this->coefficient);
int num2 = stoi(op1.coefficient);
// use to_string to set coefficient
std::string s = std::to_string(num1 - num2);
temp.coefficient = s;
temp.variable = this->variable;
temp.exponent = this->exponent;
}
else {
std::cout << "Exponents must match\n";
}
}
else {
std::cout << "Variables must match\n";
}
return temp; // return copy of temporary object
}
// assignment operator; Polynomial - Polynomial
// A member function takes an implicit first parameter
Polynomial Polynomial::operator=(Polynomial& op1){
// self assignment guard
if (this == &op1) {
return *this;//This returns as expected.
//
} // This should create a new temp, assign the second's info to it and return it.
// But all it does is return the default constructor values 1x4
Polynomial temp;
temp.coefficient = op1.coefficient;
temp.variable = op1.variable;
temp.exponent = op1.exponent;
return temp;
}
Polynomial.cpp:
Polynomial Polynomial::operator=( Polynomial op1) {
// self assignment guard
if (this == &op1) {
return *this;
// Do the copy
}
Polynomial temp;
this->coefficient = op1.coefficient;
this->variable = op1.variable;
this->exponent = op1.exponent;
return temp;
}
Polynomial.h
Polynomial operator=( Polynomial) ;
Your operator= makes no sense. There are two reasonable ways to implement operator=:
Using the copy-and-swap idiom, where the prototype for Polynomial would be:
Polynomial& operator=(Polynomial other);
//^^^^^^^^^^^ Returns a reference
^^^^^^^^^^ Receives argument by value
or,
"The hard way" (reimplementing stuff swap could do for you, and possibly implementing two different versions, one for copy assignment, and an optional one for move assignment), where the prototypes are:
Polynomial& operator=(const Polynomial& other);
//^^^^^^^^^^^ Returns a reference
^^^^^^^^^^^^^^^^^ Receives argument by const reference for copying
Polynomial& operator=(Polynomial&& other);
//^^^^^^^^^^^ Returns a reference
^^^^^^^^^^^^ Receives argument by r-value reference for moving
and both versions need to handle the possibility of self-assignment, manually implement the individual copies/moves, etc., or
The correct way for non-resource managing classes, follow the Rule of Zero: Every class should either manage an unmanaged resource (and nothing else), providing a copy constructor, assignment operator and destructor (in C++11, adding a move constructor and move assignment operator) or use solely managed resources and provide none of the above; the compiler will generate good ones for you.
Your original code was clearly going for option #2; your answer uses option #1's prototype, while still following option #2's template (involving a pointless self-assignment check), and on top of that, it does a crazy thing of not returning a reference to the object just assigned to (instead returning a temporary object that is never initialized to anything useful, and has nothing to do with any of the objects involved).
The minimalist solution here is to just fix your operator= for option #2 (since you've been told you should do a self-assignment check, and this is the only design that needs one):
Polynomial.cpp:
Polynomial& Polynomial::operator=(const Polynomial& op1) { // Changed to return by reference, and accept by const reference
// self assignment guard
if (this == &op1) {
return *this;
}
// No need to declare Polynomial temp; the target of the assignment is *this, the source is op1, there's no reason for a third unrelated Polynomial
this->coefficient = op1.coefficient;
this->variable = op1.variable;
this->exponent = op1.exponent;
return *this; // Returning *this by reference adheres to the protocol; you've just assigned, and the result of the expression is the object assigned to
}
Polynomial.h
Polynomial& operator=(const Polynomial&); // Same change as in .cpp, to return by ref, accept by const ref
That said, this is a silly solution. Your Polynomial contains nothing but std::string (and logically seems to have no reason for anything but variable to even be that; both coefficient and exponent seem like they should be an integer, floating point, or complex type, depending on use case), which is a managed type; adhering to the Rule of Zero would mean your class needn't implement copy assignment at all, nor copy construction, move construction, move assignment or a destructor, C++ would generate them all for you, simplifying your class to just:
Polynomial.h (now with nothing but the "from components" constructor and no assignment operators, because C++ makes them for you):
#pragma once
#ifndef POLYNOMIAL_H
#define POLYNOMIAL_H
#include <iostream>
#include <string>
class Polynomial {
friend std::ostream& operator<<(std::ostream&, const Polynomial&);
friend std::istream& operator>>(std::istream&, Polynomial&);
public:
// Default Constructor
Polynomial(std::string coefficient = "1", std::string variable = "x",
std::string exponent = "4");
void setPolynomial(std::string, std::string, std::string);
Polynomial getPolynomial();
// addition operator; Polynomial + Polynomial
Polynomial operator+(const Polynomial&) const;
// subtraction operator; Polynomial - Polynomial
Polynomial operator-(const Polynomial&) const;
private:
std::string coefficient; //
std::string variable; //
std::string exponent; //
};
#endif
Polynomial.cpp:
// Overloaded stream insertion and stream extraction operators
// for class PhoneNumber.
#include "Polynomial.h"
#include <utility> // For std::move
#include <iomanip>
using namespace std;
// default constructor; conversion constructor that converts
// Changed: Added actual initialization of fields from arguments (previously unused)
Polynomial::Polynomial(std::string co, std::string va, std::string ex) : coefficient(std::move(co)), variable(std::move(va)), exponent(std::move(ex)) {}
// Setters
void Polynomial::setPolynomial(std::string co, std::string va, std::string ex) {
// Changed: Using std::move since we received by value, so we can empty
// large strings more efficiently by transferring ownership from the copies that
// are about to go away anyway
this->coefficient = std::move(co);
this->variable = std::move(va);
this->exponent = std::move(ex);
}
// Getters
// Note: This function makes no sense; it's basically equivalent to just using the
// copy constructor, so if you have Polynomial a and b:
// a = b.getPolynomial();
// is just a long-winded way to spell:
// a = b;
// (and it won't work if b is const, because the function wasn't declared const)
Polynomial Polynomial::getPolynomial() { return *this; }
// overloaded stream insertion operator; cannot be a member function
// if we would like to invoke it with cout << somePhoneNumber;
ostream& operator<<(ostream& output, const Polynomial& number) {
output << "Coefficient: " << number.coefficient
<< "\nVariable: " << number.variable
<< "\nExponent: " << number.exponent << "\n"
<< "" << number.coefficient << "" << number.variable << "^"
<< number.exponent << "\n";
return output; // enables cout << a << b << c;
}
// overloaded stream extraction operator; cannot be a member function
// if we would like to invoke it with cin >> somePhoneNumber;
istream& operator>>(istream& input, Polynomial& number) {
input >> setw(1) >> number.coefficient; // input area code
input >> setw(1) >> number.variable; // input exchange
input >> setw(1) >> number.exponent; // input line
return input; // enables cin >> a >> b >> c;
}
// addition operator; Polynomial + Polynomial
// A member function takes an implicit first parameter
Polynomial Polynomial::operator+(const Polynomial& op1) const {
Polynomial temp; // temporary result
if (this->variable == op1.variable) {
if (this->exponent == op1.exponent) {
// Use stoi string to int
int num1 = stoi(this->coefficient);
int num2 = stoi(op1.coefficient);
// use to_string to set coefficient
// Changed: Assigning result of std::to_string to coefficient directly
// avoiding temporary std::string s that would just add more copy/move work
temp.coefficient = std::to_string(num1 + num2);
temp.variable = this->variable;
temp.exponent = this->exponent;
}
else {
std::cout << "Exponents must match\n";
}
}
else {
std::cout << "Variables must match\n";
}
return temp; // return copy of temporary object
}
// substraction operator; Polynomial - Polynomial
// A member function takes an implicit first parameter
Polynomial Polynomial::operator-(const Polynomial& op1) const {
Polynomial temp; // temporary result
if (this->variable == op1.variable) {
if (this->exponent == op1.exponent) {
// Use stoi string to int
int num1 = stoi(this->coefficient);
int num2 = stoi(op1.coefficient);
// Changed: Assigning result of std::to_string to coefficient directly
// avoiding temporary std::string s that would just add more copy/move work
temp.coefficient = std::to_string(num1 - num2);
temp.variable = this->variable;
temp.exponent = this->exponent;
}
else {
std::cout << "Exponents must match\n";
}
}
else {
std::cout << "Variables must match\n";
}
return temp; // return copy of temporary object
}
Try it online!
Additional notes:
As written, failed + and - operations (due to mismatched variable/exponent) still behave as if they succeeded, returning a default initialized Polynomial. Sure, it dumps a log to std::cout, but the program still continues running with total garbage data. Those std::cout errors should really be exceptions, not simple logs.
Your comments claim the + and - operations return a copy of temp. While logically this true (it must be copyable to be used in that context), in most C++11 and later compilers, copy elision will occur (the new Polynomial will be constructed directly into the caller allocated storage; no moves, let alone copies will occur).

Vector of Objects - C++. No operator "<<" matches these operands, Error

I am a beginner in programming.I have a problem. I am trying to code the Enigma machine. I have two classes. One for Enigma, one for rotors. Rotors are small parts of the enigma machine, that doesn't matter for the problem. My problem is the error. I cannot cout, the function cout << rotors[0].GetRotor(); which should return my vector of integers. I have no idea why is that. I don't need that to my program, but I'm not sure if my adding rotor to enigma void AddRotor(Rotor rotor) { rotors.push_back(rotor); }function, called in "TakeRotors" function, works right. In my opinion, it should work well, but I can't check it. Debugger, unfortunately, doesn't show any values of vector<Rotor> rotors; permutation so I am not sure :( Any help would be great. Thank You.
Here's my full, needed code :)
#include <iostream>
#include <vector>
using namespace std;
class Rotor {
public:
vector <int> permutation;
int position;
Rotor(vector<int> permutation) {
position = 0;
permutation;
}
vector<int> GetRotor() const {
return permutation;
}
};
class Enigma {
public:
vector<Rotor> rotors;
void AddRotor(Rotor rotor) {
rotors.push_back(rotor);
}
void PrintRotor(const vector<Rotor>& rotors) {
cout << rotors[0].GetRotor(); // Error right here
cout << rotors[0].position;
}
void setupRotor(int index) {
Rotor rotor = rotors[index];
}
void MoveRotor(int index) {
rotors[index].position++;
cout << "Before" << endl;
// cout << rotors[index].permutation.data << ' ';
Enigma::PrintRotor(rotors);
rotate(rotors[index].permutation.begin(), rotors[index].permutation.begin() + rotors[index].permutation.size(), rotors[index].permutation.end());
cout << "After" << endl;
Enigma::PrintRotor(rotors);
}
};
vector<int> take_numbers(int number) {
vector<int> numbers;
for (int i = 0; i < number; i++) {
int number;
cin >> number;
numbers.push_back(number);
}
return numbers;
}
void take_rotors(int number_letters, Enigma* enigma) {
int numberOfRotors;
// int numberOfNotch, positionOfNotch;
cout << "Give number of Rotors" << endl;
cin >> numberOfRotors;
for (int i=0; i < numberOfRotors; i++) {
vector<int> permutation = take_numbers(number_letters);
Rotor Rotor(permutation);
enigma->AddRotor(Rotor); // I am not sure if it adds Rotors fine.
}
}
int main()
{
Enigma enigma;
int number_letters, move_rotor;
cout << "Give number of letters in alphabet" << endl;
cin >> number_letters;
take_rotors(number_letters, &enigma);
// take_reflectors(number_letters, &enigma);
cout << "Which rotor do you want to move (index)" << endl;
cin >> move_rotor;
enigma.MoveRotor(move_rotor);
return 0;
}
There is no operator<<(std::ostream&,const std::vector<int>&) if you want it you need to supply your own. However, overloading operators for types you don't own is not recommended, so I would rather write a function:
void print_vector(std::ostream& out, const std::vector<int>& vect) {
for (int i : vect) {
out << i << '\n';
}
}
That you can call like this
print_vector(std::cout, rotors[0].GetRotor());
Alternatively you can supply an overload for << that prints all the Rotor:
std::ostream& operator<<(std::ostream&,const Rotor& rotor) {
out << rotor.position;
for (auto& i : rotor.GetRotor()) {
out << i;
}
// modify and add more to your likings
return out;
}
Once you have that you can also provide an overload to print a vector of rotors that you can use in Enigma::PrintRotor (which currently only prints the first element of the vector):
std::ostream& operator<<(std::ostream& out,const std::vector<Rotor>& rotors) {
for (const auto& r : rotors) {
out << r << '\n';
}
return out;
}
PS your naming is a little confusing. A Rotor has a GetRotor which returns permutations !?! I strongly suggest to use better names. If I have Rotor r; then r is the Rotor and it is not obvious what a GetRotor will do. Maybe rename it to GetPermutations?

C++ copy c'tor does now take action. not clear why [duplicate]

This question already has answers here:
What's the difference between assignment operator and copy constructor?
(8 answers)
Closed 4 years ago.
I have this code:
the output of the code is:
cons intcons op+ intcons ;
copycons op+ intcons op+= ;
get_val 3
class declaration::
#include<iostream>
using namespace std;
class Int {
public:
// constructors
Int() : val_(0) { cout << "cons "; }
Int(int n) { val_ = n; cout << "intcons "; }
Int(const Int &v) : val_(v.val_) { cout << "copycons "; }
Int(Int &&v_) { val_ = v_.val_; cout << "mov ctor " ; };
// operations
int get_val() {
cout << "get_val "; return val_;
}
Int operator+(const Int &v) {
cout << "op+ ";
return Int(val_ + v.val_);
}
Int & operator=(const Int &v) {
cout << "op= ";
if (this != &v) {
val_ = v.val_;
}
return *this;
}
Int & operator+=(const Int &v) {
cout << "op+= ";
val_ += v.val_;
return *this;
}
private:
int val_; // value stored in this Int
};
and this is main:
int main(){
Int zero;
Int one = zero + 1;
cout << ";\n";
Int two = zero;
two += one + one;
cout << ";\n";
cout << two.get_val() + 1; cout << endl;
return 0;
}
I was looking at the codes output, and I could agree with each operation that happens and with every output. but one thing isn't clear to me at all. I wonder, why in the first line of the output there isn't use with the copy c'tor?
at first I though maybe it is a move c'tor.
then I built one and it doesn't seemed like the compiler was using it.
can anyone please tell me what is going on? thank you!
I think you are confusing the assignment operator with the copy constructor.
Int two = zero; will cause the copy constructor to be called.
two = zero or two = 1 will cause the assignment operator to be called.
https://techdifferences.com/difference-between-copy-constructor-and-assignment-operator.html

Why overloaded operator << works sometimes but other times doesn't

I don't know why cout << da << '\n' works fine,but std::cout << next_Monday(da) << '\n' went wrong. Why the direct Date object can output, but the return Date can't.
Why overloaded operator << works sometimes but other times doesn't.
here is my code..
#include <iostream>
#include <stdlib.h>
struct Date {
unsigned day_: 5;
unsigned month_ : 4;
int year_: 15;
};
std::ostream& operator<<(std::ostream& out,Date& b)
{
out << b.month_ << '/' << b.day_ << '/' << b.year_;
return out;
}
std::istream& operator>>(std::istream& in,Date& b);
Date next_Monday(Date const &d);
int main()
{
Date da;
std::cin >> da;
std::cout << da << '\n';
std::cout << next_Monday(da) << '\n';
return 0;
}
this is what clang said: (I use g++ to invoke)
excercise19DateManipulate.cpp:114:18: error: invalid operands to binary
expression ('ostream' (aka 'basic_ostream<char>') and 'Date')
std::cout<< next_Monday(da) <<'\n';
~~~~~~~~^ ~~~~~~~~~~~~~~~
Because you can't bind a temporary to a non-const lvalue reference. Change the operator to take a const reference:
std::ostream& operator<<(std::ostream& out, const Date& b)
You never defined the "next_Monday()" function as far as I can see, you only declared it.

C++ Using classes with boost::lexical_cast

I want to use my Test class with boost::lexical_cast. I have overloaded operator<< and operator>> but It gives me runtime error.
Here is my code:
#include <iostream>
#include <boost/lexical_cast.hpp>
using namespace std;
class Test {
int a, b;
public:
Test() { }
Test(const Test &test) {
a = test.a;
b = test.b;
}
~Test() { }
void print() {
cout << "A = " << a << endl;
cout << "B = " << b << endl;
}
friend istream& operator>> (istream &input, Test &test) {
input >> test.a >> test.b;
return input;
}
friend ostream& operator<< (ostream &output, const Test &test) {
output << test.a << test.b;
return output;
}
};
int main() {
try {
Test test = boost::lexical_cast<Test>("10 2");
} catch(std::exception &e) {
cout << e.what() << endl;
}
return 0;
}
Output:
bad lexical cast: source type value could not be interpreted as target
Btw I'm using Visual Studio 2010 But I've tried Fedora 16 with g++ and got the same result!
Your problem comes from the fact that boost::lexical_cast does not ignore whitespaces in the input (it unsets the skipws flag of the input stream).
The solution is to either set the flag yourself in your extraction operator, or just skip one character. Indeed, the extraction operator should mirror the insertion operator: since you explicitely put a space when outputting a Test instance, you should explicitely read the space when extracting an instance.
This thread discusses the subject, and the recommended solution is to do the following:
friend std::istream& operator>>(std::istream &input, Test &test)
{
input >> test.a;
if((input.flags() & std::ios_base::skipws) == 0)
{
char whitespace;
input >> whitespace;
}
return input >> test.b;
}