Why move assignment is called - c++11

Please tell me why move assignment is called in the following code.
In expression return Foo(static_cast<int>(value));, static_cast<int>(value) is rvalue, so move assignment is called. However, in expression return Foo(value);, value is an lvalue. Why move assignment is called instead of Foo(int val);
#include <bits/stdc++.h>
using namespace std;
class Foo {
public:
Foo() {}
Foo(int val)
{
value = val;
}
Foo(Foo& foo)
{
value = foo.value;
cout << "call Foo(Foo& foo)" << endl;
}
Foo(Foo&& foo)
{
value = foo.value;
foo.value = 0;
cout << "call Foo(Foo &&foo)" << endl;
}
Foo& operator=(Foo &foo)
{
value = foo.value;
cout << "call operator=(Foo& foo)" << endl;
return *this;
}
Foo& operator=(Foo &&foo)
{
value = foo.value;
foo.value = 0;
cout << "call operator=(Foo&& foo)" << endl;
return *this;
}
private:
int value;
};
Foo operator"" fo(unsigned long long value)
{
if (value < INT_MAX) {
// return Foo(static_cast<int>(value)); // call operator=(Foo&& foo)
return Foo(value); // call operator=(Foo&& foo)
} else {
throw "Over Range";
}
}
int main()
{
Foo foo;
foo = 123fo;
return 0;
}

Related

when return type is auto&& in C++14

template <class T>
auto &&f(T &&param) {
return param;
}
auto test() {
int a = 1;
cout << (f(1) = a) << endl;
cout << (f(1) = 2) << endl;
}
I cannot understand why the return type of f(1) is int&, and why f(1) can be assigned to both left value and right value

push_back() binary tree into vector

I'm trying to put all the elements from a binary search tree into a vector, in order. Here is the function:
edit: adding instructions for clarity.
Write a class for implementing a simple binary search tree capable of storing numbers. The class should have member functions:
void insert(double x)
bool search(double x)
void inorder(vector <double> & v)
The insert function should not use recursion directly or indirectly by calling a recursive function. The search function should work by calling a private recursive member function
bool search(double x, <double> & v )
The inorder function is passed an initially empty vector v; if fills v with the inorder list of numbers stored in the binary search tree. Demonstrate the operation of the class using a suitable driver program.
EDIT: Added full code for clarity.
#include "stdafx.h"
#include <iostream>
#include <vector>
class BinaryTree {
private:
struct TreeNode {
double value;
TreeNode *left;
TreeNode *right;
TreeNode(double value1,
TreeNode *left1 = nullptr,
TreeNode *right1 = nullptr) {
value = value1;
left = left1;
right = right1;
}
};
TreeNode *root; //pointer to the root of the tree
bool search(double x, TreeNode *t) {
while (t) {
std::cout << "running through t." << std::endl;
if (t->value == x) {
return true;
}
else if (x < t->value) {
std::cout << "wasn't found, moving left." << std::endl;
search(x, t->left);
}
else {
std::cout << "wasn't found, moving right." << std::endl;
search(x, t->right);
}
}
std::cout << "wasn't found." << std::endl;
return false;
}
public:
std::vector<TreeNode> v;
BinaryTree() {
root = nullptr;
}
void insert(double x) {
TreeNode *tree = root;
if (!tree) {
std::cout << "Creating tree." << x << std::endl;
root = new TreeNode(x);
return;
}
while (tree) {
std::cout << "Adding next value." << std::endl;
if (tree->value == x) return;
if (x < tree->value) {
tree = tree->left;
tree->value = x;
}
else {
tree = tree->right;
tree->value = x;
}
}
}
bool search(double x) {
return search(x, root);
}
void inOrder(std::vector <double> & v) {
{
if (left)
left->inOrder(v);
v.push_back(value);
if (right)
right->inOrder(v);
}
}
TreeNode* left = nullptr;
TreeNode* right = nullptr;
double value;
};
int main() {
BinaryTree t;
std::cout << "Inserting the numbers 5, 8, 3, 12, and 9." << std::endl;
t.insert(5);
t.insert(8);
t.insert(3);
t.insert(12);
t.insert(9);
std::cout << "Looking for 12 in tree." << std::endl;
if (t.search(12)) {
std::cout << "12 was found." << std::endl;
}
std::cout << "Here are the numbers in order." << std::endl;
return 0;
}
I'm unable to get the values to push into the vector. Any ideas as to how I can accomplish this?
You would normally do this recursively:
#include <vector>
class TreeNode {
void inOrder(std::vector<double>& v) const
{
if (left)
left->inOrder(v);
v.push_back(value);
if (right)
right->inOrder(v);
}
TreeNode* left = nullptr;
TreeNode* right = nullptr;
double value;
};
Edit: added #include <vector>
Edit2: That is how I would do it. Feel free to ask any questions:
#include <iostream>
#include <vector>
class BinaryTree {
private:
struct TreeNode {
double value;
TreeNode *left = nullptr;
TreeNode *right = nullptr;
TreeNode(double value1)
: value(value1)
{}
void inOrder(std::vector <double> & v) {
if (left)
left->inOrder(v);
v.push_back(value);
if (right)
right->inOrder(v);
}
};
TreeNode *root = nullptr; //pointer to the root of the tree
bool search(double x, TreeNode *t) {
while (t) {
std::cout << "running through t." << std::endl;
if (t->value == x) {
return true;
}
else if (x < t->value) {
std::cout << "wasn't found, moving left." << std::endl;
return search(x, t->left);
}
else {
std::cout << "wasn't found, moving right." << std::endl;
return search(x, t->right);
}
}
std::cout << "wasn't found." << std::endl;
return false;
}
public:
BinaryTree() {}
void insert(double x) {
TreeNode *tree = root;
if (!tree) {
std::cout << "Creating tree." << x << std::endl;
root = new TreeNode(x);
return;
}
while (tree) {
std::cout << "Adding next value." << std::endl;
if (tree->value == x) return;
if (x < tree->value) {
if (!tree->left)
{
tree->left = new TreeNode(x);
return;
}
tree = tree->left;
}
else {
if (!tree->right)
{
tree->right = new TreeNode(x);
return;
}
tree = tree->right;
}
}
}
bool search(double x) {
return search(x, root);
}
void inOrder(std::vector<double>& v)
{
root->inOrder(v);
}
};
int main() {
BinaryTree t;
std::cout << "Inserting the numbers 5, 8, 3, 12, and 9." << std::endl;
t.insert(5);
t.insert(8);
t.insert(3);
t.insert(12);
t.insert(9);
std::cout << "Looking for 12 in tree." << std::endl;
if (t.search(12)) {
std::cout << "12 was found." << std::endl;
}
std::cout << "Here are the numbers in order." << std::endl;
std::vector<double> v;
t.inOrder(v);
std::cout << "values in order:";
for (double val : v)
{
std::cout << " " << val;
}
std::cout << std::endl;
return 0;
}

How to take advantage of the Move Semantics for a better performance in C++11?

After many trials I still do not understand how to properly take advantage of the move semantics in order to not copy the result of the operation and just use the pointer, or std::move, to "exchange" the data pointed to. This will be very usefull to speed-up more complicated functions like f(g(),h(i(l,m),n(),p(q()))
The objective is to have:
t3={2,4,6};
t1={}; // empty
While executing the code below the output is:
t3={2,4,6};
t1={1,2,3};
Code:
namespace MTensor {
typedef std::vector<double> Tensor1DType;
class Tensor1D {
private:
//std::shared_ptr<Tensor1DType> data = std::make_shared<Tensor1DType>();
Tensor1DType * data = new Tensor1DType;
public:
Tensor1D() {
};
Tensor1D(const Tensor1D& other) {
for(int i=0;i<other.data->size();i++) {
data->push_back(other.data->at(i));
}
}
Tensor1D(Tensor1D&& other) : data(std::move(other.data)) {
other.data = nullptr;
}
~Tensor1D() {
delete data;
};
int size() {
return data->size();
};
void insert(double value) {
data->push_back(value);
}
void insert(const std::initializer_list<double>& valuesList) {
for(auto value : valuesList) {
data->push_back(value);
}
}
double operator() (int i) {
if(i>data->size()) {
std::cout << "index must be within vector dimension" << std::endl;
exit(1);
}
return data->at(i);
}
Tensor1D& operator=(Tensor1D&& other) {
if (this == &other){
return *this;
}
data = other.data;
other.data = nullptr;
return *this;
}
void printTensor(Tensor1DType info) {
for(int i=0;i<info.size();i++) {
std::cout << info.at(i) << "," << std::endl;
}
}
void printTensor() {
for(int i=0;i<data->size();i++) {
std::cout << data->at(i) << "," << std::endl;
}
}
};
} // end of namespace MTensor
In file main.cpp:
MTensor::Tensor1D scalarProduct1D(MTensor::Tensor1D t1, double scalar) {
MTensor::Tensor1D tensor;
for(int i=0;i<t1.size();++i) {
tensor.insert(t1(i) * scalar);
}
//return std::move(tensor);
return tensor;
}
int main() {
MTensor::Tensor1D t1;
t1.insert({1,2,3});
std::cout << "t1:" << std::endl;
t1.printTensor();
MTensor::Tensor1D t3(scalarProduct1D(t1,2));
std::cout << "t3:" << std::endl;
t3.printTensor();
std::cout << "t1:" << std::endl;
t1.printTensor();
return 0;
}
Your use of new is a red flag, especially on a std::vector.
std::vectors support move semantics natively. They are a memory management class. Manual memory management of a memory management class is a BIG red flag.
Follow the rule of 0. =default your move constructor, move assignment, copy constructor, destructor and copy assignment. Remove the * from the vector. Don't allocate it. Replace data-> with data.
The second thing you should do is change:
MTensor::Tensor1D scalarProduct1D(MTensor::Tensor1D t1, double scalar) {
As it stands you take the first argument by value. That is great.
But once you take it by value, you should reuse it! Return t1 instead of creating a new temporary and returning it.
For that to be efficient, you will want to have a way to modify a tensor in-place.
void set(int i, double v) {
if(i>data->size()) {
std::cout << "index must be within vector dimension" << std::endl;
exit(1);
}
data.at(i) = v;
}
which gives us:
MTensor::Tensor1D scalarProduct1D(MTensor::Tensor1D t1, double scalar) {
for(int i=0;i<t1.size();++i) {
ts.set(i, t1(i) * scalar);
}
return t1; // implicitly moved
}
We are now getting close.
The final thing you have to do is this:
MTensor::Tensor1D t3(scalarProduct1D(std::move(t1),2));
to move the t1 into the scalarProduct1D.
A final problem with your code is that you use at and you check bounds. at's purpose is to check bounds. If you use at, don't check bounds (do so with a try/catch). If you check bounds, use [].
End result:
typedef std::vector<double> Tensor1DType;
class Tensor1D {
private:
//std::shared_ptr<Tensor1DType> data = std::make_shared<Tensor1DType>();
Tensor1DType data;
public:
Tensor1D() {};
Tensor1D(const Tensor1D& other)=default;
Tensor1D(Tensor1D&& other)=default;
~Tensor1D()=default;
Tensor1D& operator=(Tensor1D&& other)=default;
Tensor1D& operator=(Tensor1D const& other)=default;
Tensor1D(const std::initializer_list<double>& valuesList) {
insert(valuesList);
}
int size() const {
return data.size();
};
void insert(double value) {
data.push_back(value);
}
void insert(const std::initializer_list<double>& valuesList) {
data.insert( data.end(), valuesList.begin(), valuesList.end() );
}
double operator() (int i) const {
if(i>data.size()) {
std::cout << "index must be within vector dimension" << std::endl;
exit(1);
}
return data[i];
}
void set(int i, double v) {
if(i>data->size()) {
std::cout << "index must be within vector dimension" << std::endl;
exit(1);
}
data.at(i) = v;
}
static void printTensor(Tensor1DType const& info) {
for(double e : info) {
std::cout << e << "," << std::endl;
}
}
void printTensor() const {
printTensor(data);
}
};
MTensor::Tensor1D scalarProduct1D(MTensor::Tensor1D t1, double scalar) {
for(int i=0;i<t1.size();++i) {
t1.set(i, t1(i) * scalar);
}
return t1;
}
int main() {
MTensor::Tensor1D t1 = {1,2,3};
std::cout << "t1:" << std::endl;
t1.printTensor();
MTensor::Tensor1D t3(scalarProduct1D(std::move(t1),2));
std::cout << "t3:" << std::endl;
t3.printTensor();
std::cout << "t1:" << std::endl;
t1.printTensor();
return 0;
}
with a few other minor fixes (like using range-for, DRY, etc).
You need to move t1 when calling scalarProduct1D, otherwise you'll make a copy:
MTensor::Tensor1D t3(scalarProduct1D(std::move(t1),2));
You need to explicitly use std::move because t1 is an lvalue expression.
Note that you'll have to fix your printing functions to avoid dereferencing nullptr if you want accessing the moved-from object to be a valid operation. I instead suggest to avoid making method invocation on moved-from objects valid as it requires additional checks and doesn't follow the idea of "this object has been moved, now it's in an invalid state".
live wandbox example

Not able to store data in a private member variable from a const member function - FIX8 c++

This is my header :
class my_router_client : public FIX8::my::mine_Router {
private:
mine_session_client& _session;
mutable std::vector<std::string> vSymbolList;
public:
my_router_client(mine_session_client& session) : _session(session) {}
virtual bool operator() (const FIX8::my::SecurityList *msg) const;
void sendToServer(FIX8::Message *);
void logout();
void itertool() const;
};
I am trying to save the data obtained from security list response to the vSymbolList vector. After handling security response I am trying to iterate through the vector by itertool method. But every time I end up with an empty vector. I tried printing the contents of the vector inside securitylist response function
virtual bool operator() (const FIX8::CX::SecurityList *msg) const;
and I am able to print the contents. Is it some kind of race condition inside threads?
this is the security list response handler
bool cx_router_client::operator() (const CX::SecurityList *msg) const
{
GroupBase *dad(msg->find_group< CX::SecurityList::NoRelatedSym >());
if (dad) {
for (size_t cnt(0); cnt < dad->size(); ++cnt) {
CX::Symbol symbol;
MessageBase *details(dad->get_element(cnt));
details->get(symbol);
string ss;
ss = symbol();
vSymbolList.push_back(ss);
// cout << "at :: :: " << vSymbolList[cnt] << endl;
}
cout << "no of symbol : " << vSymbolList.size() << endl;
hypersleep<h_seconds>(1);
}
return true;
}
This is the itertool method :
void my_router_client::itertool() const
{
cout << "symbol list vector size inside itertool:: " << vSymbolList.size() << endl;
stringstream ss;
ss << this_thread::get_id();
uint64_t id = stoull(ss.str());
cout << "Thread ID #### " << id << endl;
vector<string>::iterator it = this->vSymbolList.begin();
while (it != vSymbolList.end()) {
cout << *it << endl;
it++;
}
}
This is how I use the them in main :
int main()
{
const string conf_file("myfix_client.xml");
unique_ptr<ClientSessionBase> mc(new ClientSession<mine_session_client>(my::ctx(), conf_file, "DLD1"));
mc->start(false, next_send, next_receive, mc->session_ptr()->get_login_parameters()._davi());
hypersleep<h_seconds>(1);
my_router_client *test = new my_router_client(static_cast< mine_session_client& > (*mc->session_ptr()));
hypersleep<h_seconds>(1);
test->sendToServer(makeSecurityListRequest());
hypersleep<h_seconds>(1);
test->itertool();
while(1);
}

.compare not matching a string pulled from an object

I am trying to go threw a vector of Student objects. If I find a matching ID to the one I am searching for it will display their info.
However, when I try to find a specific ID .compare isn't seeing a match even though it should.
My output: first line is the ID I am looking for, second is the current ID being looked at, then is the result of the compare.
a11111111
a22222222
-1
no match
a11111111
a11111111
-1
no match
Asked for more of the code so here is the entire program: (issue in displayID)
header file
#ifndef structures_h
#define structures_h
#include <vector>
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <fstream>
#include <sstream>
#include <string>
#include <algorithm>
#include <stdio.h>
#include <map>
using namespace std;
main program
#endif
typedef pair<string, string> Name; // first name, last name
typedef map<string, int> Grades; // map courses to scores
#include "struct.h"
class Student {
public:
void display(ostream& os) const;
void setId(string);
void setName(string, string);
void setGrades(string, int);
string getId();
string getName();
void getGrades();
bool operator<(const Student &rhs) const { return id_ < rhs.id_; }
private:
string id_; // e.g. "a22222222"
Name name_; // e.g. {"ned", "flanders"}
Grades grades_;
};
void Student::setId(string id) {
id_ = id;
}
string Student::getId() {
return id_;
}
void Student::setName(string first, string last) {
name_ = pair<string,string>(first, last);
}
string Student::getName() {
return get<0>(name_) + ' ' + get<1>(name_);
}
void Student::setGrades(string course, int score) {
grades_.insert(make_pair(course, score));
}
void Student::getGrades() {
for(auto it = grades_.begin(); it != grades_.end(); ++it) {
cout << it -> first << ' ' << it -> second << endl;
}
}
vector<Student> addStudent(int count, int x, vector<Student>& vStu, string file) {
string line, first, last;
ifstream infile(file);
while (getline(infile, line)) {
vStu.push_back(Student());
vStu[count].setId(line);
getline(infile, line);
istringstream iss(line);
if (!(iss >> first >> last)) {
cout << "failed to get name" << endl;
break;
}
vStu[count].setName(first, last);
getline(infile, line);
istringstream iss2(line);
if (!(iss2 >> x)) {
cout << "failed to get class number" << endl;
break;
}
for (int i = 0; i < x; i++) {
string sClass;
int grade;
getline(infile, line);
istringstream iss3(line);
if (!(iss3 >> sClass >> grade)) {
cout << "failed to get class and grade" << endl;
break;
}
vStu[count].setGrades(sClass, grade);
}
count++;
}
return vStu;
}
void display(vector<Student>& vStu) {
sort(vStu.begin(), vStu.end());
cout << endl;
int count = vStu.size();
for (int i = 0; i<count;i++) {
cout << vStu[i].getId() << endl;
cout << vStu[i].getName() << endl;
vStu[i].getGrades();
cout << endl;
}
}
void displayID(vector<Student>& vStu, string ID) {
int count = vStu.size();
string test;
ID = "a11111111";
for (int i = 0; i<count;i++) {
cout<< endl;
test = vStu[i].getId();
cout << ID << endl;
cout << test << endl;
cout << ID.compare(test) << endl;
if (ID.compare(test) == 0) {
cout << "match" << endl;
cout << vStu[i].getId() << endl;
cout << vStu[i].getName() << endl;
vStu[i].getGrades();
cout << endl;
} else {
cout << "no match" << endl;
}
}
cout << endl;
}
void mainMenu(vector<Student>& vStu) {
string input;
string word;
vector<string> com;
while(1) {
cout << "Enter command: ";
getline(cin,input);
istringstream iss(input);
while(iss >> word) {
com.push_back(word);
}
for (int i = 0; i < (int)com.size(); i++) {
transform(com[i].begin(), com[i].end(), com[i].begin(), ::tolower);
if (com[i] == "show") {
display(vStu);
} else if (com[i] == "showid") {
displayID(vStu, "a11111111");
}
}
com.clear();
}
}
int main(int argc, char *argv[]) {
vector<Student> vStu;
int count = 0, x = 0;
if (argc != 2) {
cout << "Incorrectly called" << endl;
cout << " " << argv[0] << ' ' << "<filename>" << endl;
return 1;
}
addStudent(count, x, vStu, argv[1]);
mainMenu(vStu);
}
The only possibility I see is that there is some whitespace at the end of the string that gets passed into your function. Try trimming the end of the string's like this this thread suggests before comparing and see if they still don't compare correctly.

Resources