I have 2 classes HttpRequest and RequestParser both implementing the operator=. Each have a variable referencing to HttpRequest and RequestParser as so:
class HttpRequest : public Message {
private:
std::string _method;
std::string _path;
bool _requestReceived;
RequestParser _parser;
...
HttpRequest &HttpRequest::operator=(HttpRequest const &rhs) {
if (this != &rhs) {
_method = rhs._method;
_path = rhs._path;
_parser = rhs._parser;
}
}
class RequestParser {
private:
std::stringstream _inReceive;
bool _headersReceived;
HttpRequest &_request;
...
RequestParser &RequestParser::operator=(RequestParser const &rhs) {
if (this != &rhs) {
_inReceive << rhs._inReceive.str();
_headersReceived = rhs._headersReceived;
_request = rhs._request;
}
}
The problem is that they each call operator= repeatedly.
#28 0x5641ead38f57 in RequestParser::operator=(RequestParser const&) srcs/http/RequestParser.cpp:98
#29 0x5641ead368f1 in HttpRequest::operator=(HttpRequest const&) srcs/http/HttpRequest.cpp:64
#30 0x5641ead38f57 in RequestParser::operator=(RequestParser const&) srcs/http/RequestParser.cpp:98
#31 0x5641ead368f1 in HttpRequest::operator=(HttpRequest const&) srcs/http/HttpRequest.cpp:64
#32 0x5641ead38f57 in RequestParser::operator=(RequestParser const&) srcs/http/RequestParser.cpp:98
I have no idea how to fix this.
Related
I have code like below and I need to write a global function overloading the addition operator for objects of this class so that the resulting object represents the concatenation of two strings separated by the '+' sign. Can someone help me?
class A {
char* str;
// ...
};
Such operator should have access to content of class and to create a new instance of class A which it returns. Assuming there is no public interface to access str such operator have to be a friend function with signature similar to one below
class A {
char* str;
// ...
friend A operator+ (const A& arg1, const A& arg2)
{
A temp{arg1}; // assuming that A have a copy constructor
// perform concatenation of temp and arg2 here
return temp;
}
};
Try something like this:
class A
{
char* str;
// ...
public:
A(const char *s = nullptr) : str(nullptr) {
if (s) {
str = new char[strlen(s)+1]);
strcpy(str, s);
}
}
A(const A &src) : A(src.str) {}
A(A &&src) : str(src.str) { src.str = nullptr; }
~A() { delete[] str; }
A& operator= (A rhs) {
A temp{std::move(rhs)};
std::swap(str, temp.str);
return *this;
}
friend A operator+ (const A& arg1, const A& arg2)
{
A temp;
temp.str = new char[strlen(arg1.str)+1+strlen(arg2.str)+1];
sprintf(temp.str, "%s+%s", arg1.str, arg2.str);
return temp;
}
};
That being said, you really should use std::string instead of char*:
class A
{
std::string str;
// ...
public:
A(const std::string &s = "") : str(s) {}
friend A operator+ (const A& arg1, const A& arg2)
{
return A{arg1.str + "+" + arg2.str};
}
};
I defined simple conversion method
operator string() { return /*...*/; }
When I call it directly
obj.operator string()
It works fine, but when I call it this way ...
(string)obj
Result is empty string.
What's going on? (I'm using gcc c++14) (Can post code If needed)
Class
class String : public std::string {
std::string str_;
public:
String() {};
String(const String & s) {
str_ = std::string(s.str_);
};
String(String && s) {
str_ = std::string(s.str_);
};
String(const string & s) {
str_ = std::string(s);
};
String(const char * s) {
str_ = std::string(s);
};
char & operator[](size_t i) {
return str_[i];
};
String & operator=(const String & str) {
if (this != &str) {
str_ = str.str_;
}
return *this;
};
String & operator=(String && str) {
if (this != &str) {
str_ = str.str_;
}
return *this;
};
bool operator==(const String & str) {
return str_ == str.str_;
};
bool operator!=(const String & str) {
return str_ != str.str_;
};
operator string() {
return str_;
};
};
The problem is that your class is deriving from std::string.
Remove the : public std::string part and the conversion operator will be used.
You class is already declaring an std::string member (so it uses the "has-a" approach) and doesn't need the "is-a" approach.
By the way deriving from standard library classes is almost always a bad idea (they were not designed for that).
I need to have set as a class member variable, but also need it's comparision function object use the attributes of the class.
class Example
{
int _member1;
set<string, MyCmp> _myNameSet;
class MyCmp
{
Example& myEx;
MyCmp( const Example& ex) {
myEx = ex;
}
bool operator() (const string& lhs, const string& rhs)
{
/// Use "_member1" here ...
myEx._member1;
/// Do something ....
}
}
};
So here my question is, how do i pass the Example object as an argument to the MyCmp constructor? Since the "_myNameSet" is an member variable.
If it was not an member variable, there is a way i know:
void Example::functionBlah()
{
MyCmp obj(&(*this));
set<String, MyCmp> myLocalSet(obj);
}
You may use initializer list in constructor:
class Example
{
public:
Example() : _member1(0), _myNameSet(this) {}
Example(const Example&) = delete;
Example& operator = (const Example&) = delete;
// Other stuff
private:
int _member1;
set<string, MyCmp> _myNameSet;
};
I have a program that gets some data from a mysql database, calls a function to process that data, and exits. I'm getting a weird error when running it...the program crashes when the function returns a value. As I suspected it's a problem with the destructor of one of my classes. The class holds two vectors (one of doubles, the other of a date class I wrote myself). The program crashes when the vector of doubles is destroyed.
Manually erasing the vector in the destructor doesn't do anything.
When I call the destructor manually I don't get this error. It only happens when I return a value from my function. Going line-by-line the crash happens in stl_vector.h on the line
{ _M_deallocate(this->_M_impl._M_start, this->_M_impl._M_end_of_storage - this->_M_impl._M_start); }
Googling hasn't been very helpful...I found that assigning a value outside the size of the vector might trigger something like this but I've gone through my code and ensured that that doesn't happen.
The error:
Program received signal SIGTRAP, Trace/breakpoint trap.
In ntdll!DbgUiConnectToDbg () (C:\WINDOWS\system32\ntdll.dll)
The call stack:
#0 7C90120F ntdll!DbgUiConnectToDbg() (C:\WINDOWS\system32\ntdll.dll:??)
#1 7C96EE31 ntdll!RtlpNtMakeTemporaryKey() (C:\WINDOWS\system32\ntdll.dll:??)
#2 7C96F26E ntdll!RtlpNtMakeTemporaryKey() (C:\WINDOWS\system32\ntdll.dll:??)
#3 7C970456 ntdll!RtlpNtMakeTemporaryKey() (C:\WINDOWS\system32\ntdll.dll:??)
#4 7C94BAFC ntdll!LdrFindEntryForAddress() (C:\WINDOWS\system32\ntdll.dll:??)
#5 00000000 0x006b0000 in ??() (??:??)
#6 00000000 0x50000061 in ??() (??:??)
#7 00000000 0x00f57008 in ??() (??:??)
#8 00000000 0x006b0000 in ??() (??:??)
#9 00000000 0x00f57008 in ??() (??:??)
#10 00000000 0x40000060 in ??() (??:??)
#11 00000000 0x00f60558 in ??() (??:??)
#12 00000000 0x002240b0 in ??() (??:??)
#13 00000000 0x00223804 in ??() (??:??)
#14 7C96F2D7 ntdll!RtlpNtMakeTemporaryKey() (C:\WINDOWS\system32\ntdll.dll:??)
#15 7C91A1BA ntdll!RtlpUnWaitCriticalSection() (C:\WINDOWS\system32\ntdll.dll:??)
#16 77C2C2DE msvcrt!free() (C:\WINDOWS\system32\msvcrt.dll:??)
#17 00000000 0x006b0000 in ??() (??:??)
#18 00000000 0x00000000 in ??() (??:??)
Using MinGW in Code::Blocks on winxp. There's a ton of code and since I don't really know where it goes wrong I don't know what to include here...
Thanks for the help.
Edit:
A bunch of code that may or may not be relevant:
Fetching the data, initializing the dated_observations objects (the vectors in these are causing the crashes) and adding the data to them (note that from this point up until the function terminates, I only read values from these objects...no elements are added, modified, or deleted):
query_ss << "SELECT * FROM stock_data WHERE stock_id = " << stock1_id;
mysql_query(connect,query_ss.str().c_str());
query_ss.str("");
res_set = mysql_store_result(connect);
numrows = mysql_num_rows(res_set);
dated_observations s1_p(numrows);
dated_observations s1_r(numrows);
for(i = 0; i < numrows; i++) {
row = mysql_fetch_row(res_set);
s1_p.my_insert(row[2], std::atof(row[3]));
s1_r.my_insert(row[2], std::atof(row[4]));
}
The dated class:
#ifndef _DATED_H_
#define _DATED_H_
#include <vector>
#include "date.h" // my date class
template <class T> class dated {
private:
int counter;
public:
vector<date> dates_;
vector<T> elements_;
//dated<T>();
dated<T>(const int&);
dated<T>(const dated<T>&);
dated<T> operator= (const dated<T>&);
~dated() { clear(); };
void clear(); // erasing
void insert(const date&, const T&); // insert somewhere
void my_insert(const date&, const T&); // insert at the end
bool empty() const ;
int size() const ;
bool contains(const date& d) const ;
date date_at(const int& t) const ; // accessing elements, here dates
T element_at(const int& t) const ; // index directly
T element_at(const date& d) const ; // index indirectly, specify what date
//date last_date() const ;
//T last_element() const;
// next: the element either on date d, if d is here, else the last observation before d.
T current_element_at(const date& d) const ;
vector<T> elements() const; // all elements as vector<T>
vector<date> dates() const; // all dates as vector<date>
date first_date() const; // simple queries
date last_date() const;
T first_element() const;
T last_element() const;
void set_counter(int cnt);
int get_counter() const;
int index_of_date(const date& d) const; // when searching in the data,
int index_of_last_date_before(const date& d) const; // these are useful functions
int index_of_first_date_after(const date& d) const;
int no_observations_between(const date&first, const date& last) const;
void remove(const date&); // removing one or more elements
void remove_between_including_end_points(const date&, const date&);
void remove_between(const date&, const date&);
void remove_before(const date&);
void remove_after(const date&);
};
#include "dated_main.h"
#include "dated_search.h"
#include "dated_remove.h"
template<class T> dated<T> observations_between(const dated<T>& obs,const date&first, const date& last);
template<class T> dated<T> observations_after(const dated<T>& obs, const date& first);
template<class T> dated<T> observations_before(const dated<T>& obs, const date& last);
template<class T> dated<T> end_of_year_observations(const dated<T>&);
template<class T> dated<T> beginning_of_month_observations(const dated<T>&);
template<class T> dated<T> end_of_month_observations(const dated<T>&);
template<class T> dated<T> observations_matching_dates(const dated<T>& obs, const vector<date>& dates);
#include "dated_util.h"
#endif
Some of the methods of the dated class:
//template<class T> dated<T>::dated(){;}; // not necessary to do anything,
template<class T>dated<T>::dated(const int& init_size = 0) {
// for speed, initialize first with correct size and then copy
counter = 0;
if(init_size > 0) {
dates_=vector<date>(init_size);
elements_=vector<T>(init_size);
}
};
template<class T>dated<T>::dated(const dated<T>& dobs) {
// for speed, initialize first with correct size and then copy
counter = 0;
dates_=vector<date>(dobs.size());
elements_=vector<T>(dobs.size());
for (int t=0;t<dobs.size();++t){
dates_[t] = dobs.date_at(t);
elements_[t] = dobs.element_at(t);
};
};
template<class T> dated<T> dated<T>::operator= (const dated<T>& dobs) {
counter = 0;
if (this==&dobs) return *this; // check against self assignment;
clear();
dates_=vector<date>(dobs.size());
elements_=vector<T>(dobs.size());
for (int t=0;t<dobs.size();++t){
dates_[t] = dobs.date_at(t);
elements_[t] = dobs.element_at(t);
};
return *this;
};
template<class T> dated<T>::~dated();
template<class T> bool dated<T>::empty() const { return (dates_.size()<1); };
template<class T> int dated<T>::size() const { return dates_.size(); };
template<class T> date dated<T>::date_at(const int& t) const { // accessing with bounds checking
if ( (t>=0) && (t<size()) ) return dates_[t];
return date();
};
template<class T> T dated<T>::element_at(const int& t) const { // accessing with bounds checking
if ( (t>=0) && (t<size()) ) return elements_[t];
return T();
};
template<class T> void dated<T>::set_counter(int cntr){
counter = cntr;
}
template<class T> int dated<T>::get_counter() const {
return counter;
}
template<class T> T dated<T>::element_at(const date& d) const {
if (!contains(d)) return T();
return elements_[index_of_date(d)];
};
template <class T> void dated<T>::my_insert(const date& d, const T& obs) {
if (!d.valid()) return;
elements_[counter] = obs;
dates_[counter] = d;
counter++;
};
template<class T> void dated<T>::clear() {
dates_ .erase(dates_ .begin(),dates_ .end());
elements_ .erase(elements_ .begin(),elements_ .end());
};
The dated_observations class:
#ifndef _DATED_OBS_H_
#define _DATED_OBS_H_
#include "dated.h" // templated dated<> class
#include <string> // ANSI string class
class dated_observations : public dated<double>{
private:
string title_;
public:
dated_observations(const dated_observations& dobs); //copy constructor
dated_observations(const int& init_size = 0) : dated<double>(init_size) {;}
void clear();
~dated_observations() { clear(); };
void set_title(string s); // title
string title() const;
int no_obs() const;
int no_obs_between(const date& d1, const date& d2) const;
int no_obs_before(const date& d) const;
int no_obs_after(const date& d) const;
};
///// io
ostream& operator << (ostream&, const dated_observations& );
void print_dated_observations(ostream& of, const dated_observations& d, int precision=3);
//// mischellaneous utilities
double max_obs(dated_observations& dobs);
double min_obs(dated_observations& dobs);
bool dates_match(const dated_observations& obs1, const dated_observations& obs2);
///// picking subsets.
dated_observations observations_between(const dated_observations& obs,const date& first,const date& last);
dated_observations observations_after(const dated_observations& obs, const date& first);
dated_observations observations_before(const dated_observations& obs, const date& last);
dated_observations observations_matching_dates(const dated_observations& obs, const vector<date>& dates);
///// picking periodic elements
dated_observations beginning_of_month_observations(const dated_observations&);
dated_observations end_of_month_observations(const dated_observations&);
dated_observations end_of_year_observations(const dated_observations&);
dated_observations end_of_year_current_observations(const dated_observations&);
#endif
Some of the dated_observations methods:
dated_observations::dated_observations(const dated_observations& dobs) {
elements_ = dobs.elements_;
dates_ = dobs.dates_;
set_counter(dobs.get_counter());
}
void dated_observations::set_title(string s) { title_ = s; };
void dated_observations::clear() {
title_ = string();
dated<double>::clear();
set_counter(0);
};
Another edit:
Removing all the code between the initialization of s1_p & s1_r and the end actually removes the error. Could maybe trying to read or copy a value outside the size of the vector cause this?
I'm just toying around to watch how defining operators work. The following code gives me an error about "No candidate functions found".
Any criticism other than that of the root cause is welcome, too. Thanks!
#include <iostream>
using std::cout; using std::cin; using std::endl;
using std::string;
class SomeClass {
public:
SomeClass(int newNum, string newString) { num=newNum; str = newString; }
SomeClass& operator=(const SomeClass& rh) {
string newVal(rh.getStr());
str = newVal;
}
void setStr(string newString) { str = newString; }
const string getStr() { return str; }
string toString() { return str+str; }
private:
string str;
int num;
};
int main() {
SomeClass a(5, "five");
SomeClass b(3, "three");
cout << a.toString() << endl << b.toString() << endl;
a=b;
cout << a.toString() << endl << b.toString() << endl;
}
const string getStr() { return str; }
should be
const string& getStr() const { return str; }
Otherwise you cannot call a non-const function on a const parameter of
SomeClass& operator=(const SomeClass& rh)
Note that private, public and protected visibility is at class level, not instance level. So there is no need for a getStr() function. You could write:
SomeClass& operator=(const SomeClass& rh) {
this->str = rh.str;
return *this;
}
Everything looks fine so far except that you've not included
#include <string>
You need to include this as well.
Oh I also saw that you're not returning anything from the function:
SomeClass& operator=(const SomeClass& rh) {
string newVal(rh.getStr());
str = newVal;
return *this; //DO THIS AS WELL
}
And also, rh is a const object in this function and using it, you're calling getStr() which is a non-const function which is causing the problem. So the fix is this:
const string getStr() const { return str; }
// ^^^^^ make the function const!
And alternatively, you could've written your operator= as follows:
SomeClass& operator=(const SomeClass& rh) {
str = rh.str; //no need to create a local (temporary) variable!
return *this; //DO THIS AS WELL
}
I think its better solution!
You just need to change
const string getStr() { return str; }
to
const string getStr() const { return str; } //the 2nd const make getStr() a const member function
^^^^
This is because const object can only call const member function and you were trying to doing this:
SomeClass& operator=(const SomeClass& rh) { //here you declared rh to be const
//so in order to call getStr() from rh, you need declare getStr function to be const
string newVal(rh.getStr());
str = newVal;
return *this;
}
So your class could simply look like this:
class SomeClass {
public:
SomeClass(int newNum, string newString):num(newNum), str(newString) {/* Empty */}
SomeClass& operator=(const SomeClass& rh) {
str=rh.str;
return *this;
}
string toString() { return str+str; }
private:
string str;
int num;
};