Overriding the subscript operator in String class - c++

I am working on building a string class in C++. Currently I am trying to override the subscript operator so users can get and modify individual characters.
#ifndef STRING_HPP
#define STRING_HPP
#include "test.hpp"
#include <cstring>
#include <iosfwd>
struct String
{
// Defines the npos value.
static constexpr std::size_t npos = -1;
int len;
char *str;
String()
:len(0), str(0){}
String(char const * S)
:len(strlen(S)), str(new char[len + 1]){
assert(S != 0);
strcpy(str, S);
}
~String(){
delete[]str;
}
String (char *S, std::size_t const n)
:len(n), str(new char[len + 1]){
assert(S != 0);
assert(strlen(S) >= n);
strncpy(str, S, n);
str += '\0';
}
String operator +=(String const &S){
int n = len + S.len;
char * p = new char[n+1];
strcpy(p + len, S.str);
len = n;
str = p;
return *this;
}
char* data() const {
return this->str;
}
bool empty() const {
return (this->len == 0);
}
size_t size()const {
size_t temp = len;
return temp;
}
//assignment operator
String operator =(String const &s){
String temp(s);
swap(temp);
return *this;
}
void swap(String &s){
std::swap(len, s.len);
std::swap(str, s.str);
}
size_t find(const char c){
char * p = strchr(this->str, c);
if(p){
return (str - p);
}else{
return npos;
}
}
char &operator[](const size_t pos){
assert(pos >= 0);
assert(pos < this->size());
return str[pos];
//return output;
}
String substr(int index, int dist){
String output((this->str + index) ,dist);
return output;
}
};
// Output
std::ostream& operator<<(std::ostream&, String const&);
//String operator +=(String const &);
bool operator <(String const &, String const &);
bool operator >(String const &, String const &);
bool operator <=(String const &, String const &);
bool operator >=(String const &, String const &);
bool operator ==(String const &, String const &);
#endif
The portion of main that calls the subscript function is:
String s1 = "String";
s1[0] = 'a';
The error I am getting is:
error: passing 'const String' as 'this' argument of 'char& String::operator[](size_t)' discards qualifiers [-fpermissive]
Thanks!
Edit
Updated error message to be correct

turns out the answer is just to add a 'const' at the end of the function:
char &operator[](const size_t pos)const{
assert(pos >= 0);
assert(pos < this->size());
return str[pos];
//return output;
}

Related

What's wrong with my custom string class operator+?

I'm trying to make my own String class, and I have a problem with operator+.
When I use + as " s1 = s2 + s3 " it works.
But in case just use " s1 + s1 " or " s2 + s3 " does not work.
When I run it, I get 0xC0000005 error on 'init' function at delete[] str_; line.
I want to know what's wrong with my codes...
this is my string.h
class String
{
private:
int len_;
int capa_;
char* str_;
public:
String(const String& str);
String(const char* s = "");
~String();
const char* Print(bool show = true);
int size();
int length();
int capacity();
String& assign(const String& str);
String& assign(const char* s);
String& operator=(const String& str);
String& operator=(const char* s);
String& append(const String& str);
String& append(const char* s);
String& operator+=(const String& str);
String& operator+=(const char* s);
String operator+(const String& str);
String operator+(const char* s);
char& operator[](int index);
void shrink_to_fit();
friend std::ostream& operator<<(std::ostream& os, const String& str);
private:
void init(const char* s);
String plus(const char* s);
};
this is my string.cpp
void String::init(const char* s)
{
if (str_ == s) {}
else
{
delete[] str_;
}
len_ = strlen(s);
capa_ = len_ + 1;
str_ = new char[capa_];
strcpy_s(str_, capa_, s);
}
String::String(const String& str)
{
init(str.str_);
}
String::String(const char* s)
{
init(s);
}
String::~String()
{
delete[] str_;
}
int String::size()
{
return this->len_;
}
int String::length()
{
return strlen(this->str_);
}
int String::capacity()
{
return this->capa_;
}
String& String::assign(const String& str)
{
assign(str.str_);
return *this;
}
String& String::assign(const char* s)
{
init(s);
return *this;
}
String& String::operator=(const String& str)
{
assign(str.str_);
return *this;
}
String& String::operator=(const char* s)
{
assign(s);
return *this;
}
String& String::append(const String& str)
{
append(str.str_);
return *this;
}
String& String::append(const char* s)
{
len_ = this->len_ + strlen(s);
capa_ = len_ + 1;
char* temp = new char[capa_];
strcpy_s(temp, capa_, this->str_);
if (str_ == s) {}
else
{
delete[] str_;
}
strcat_s(temp, capa_, s);
str_ = new char[capa_];
strcpy_s(str_, capa_, temp);
delete[] temp;
return *this;
}
String& String::operator+=(const String& str)
{
append(str);
return *this;
}
String& String::operator+=(const char* s)
{
append(s);
return *this;
}
char& String::operator[](int index)
{
int index_;
if (index < 0)
{
index_ = 0;
}
else if (index > this->len_)
{
index_ = this->len_ - 1;
}
else
{
index_ = index;
}
return str_[index_];
}
String String::plus(const char* s)
{
int tempcapa = this->len_ + strlen(s) + 1;
char* temp = new char[tempcapa];
strcpy_s(temp, tempcapa, this->str_);
strcat_s(temp, tempcapa, s);
return temp;
}
String String::operator+(const String& str)
{
return plus(str.str_);
}
String String::operator+(const char* s)
{
return plus(s);
}
std::ostream& operator<<(std::ostream& os, const String& str)
{
os << str.str_;
return os;
}
void String::shrink_to_fit()
{
if (this->capa_ > this->len_ + 1)
{
char* temp = new char[len_ + 1];
strcpy_s(temp, len_ + 1, this->str_);
delete[] this->str_;
this->str_ = new char[len_ + 1];
strcpy_s(this->str_, len_ + 1, temp);
delete[] temp;
this->capa_ = len_ + 1;
}
}
const char* String::Print(bool show)
{
if (show == true)
std::cout << str_;
return str_;
}

Error with friend non-member function which gives a segmentation fault

For this project we are suppose to cover the topic of dynamic memory allocation and deallocation. The functionality of the 'operator<<; is to output(to terminal or file depending on the type of ostream& os object passed as a parameter to it) the MyString data (the C-string representation held within m_buffer). Right after my program prints to the Terminal "Access Successful." I receive a Segmentation fault (core dumped) I am quite sure that it have something to do with the operator << but I do not know how to fix this. Hence, it fails to print "Testing Operator <<()". Any Suggestions? Thank you!
//int main
int main(){
std::cout << "Testing operator[]()" << std::endl;
MyString ms_access("Access successful (NOT)");
ms_access[17] = 0;
std::cout << "Testing operator<<()" << std::endl;
cout << ms_access << endl;
}
class MyString{
public:
MyString();
MyString(const char * str);
MyString(const MyString & other_myStr);
~MyString();
size_t size() const;
size_t length() const;
const char * c_str() const;
bool operator== (const MyString & other_myStr) const;
MyString & operator= (const MyString & other_myStr);
MyString operator+ (const MyString & other_myStr) const;
char & operator[] (size_t index);
const char & operator[] (size_t index) const;
friend std::ostream & operator<<(std::ostream & os, const MyString & myStr);
private:
void buffer_deallocate();
void buffer_allocate(size_t size);
char * m_buffer;
size_t m_size;
};
//definition
std::ostream& operator<<(std::ostream& os, const MyString& myStr){
//if(os == std::cout){
os << myStr.m_buffer << std::endl;
//}
}
//will allow by-reference accessing of a specific character at index size_tindexwithin the allocated m_bufferchar arrayof a non-constqualified object.
char& MyString::operator[](size_t index){
size_t counter = 0;
while(counter != index){
counter++;
}
return m_buffer[counter];
}
//will allow by-reference accessing of a specific character at index size_tindexwithin the allocated m_bufferchar array of a constqualified object.
const char& MyString::operator[](size_t index)const{
size_t counter = 0;
while(counter != index){
counter++;
}
return m_buffer[counter];
}
void MyString::buffer_deallocate(){
if(m_buffer != NULL){
delete [] m_buffer;
}
}
void MyString::buffer_allocate(size_t size){
if(m_buffer != NULL){
buffer_deallocate();
}
m_size = size;
m_buffer = new char[m_size];
}
MyString::MyString(){
m_size = 0;
m_buffer = NULL;
}
MyString::MyString(const char *str){
m_buffer = NULL;
m_size = strlen(str);
buffer_allocate(m_size);
strcpy(m_buffer,str);
}
MyString::MyString(const MyString &other){
m_buffer = NULL;
m_size = other.m_size;
buffer_allocate(m_size);
strcpy(m_buffer,other.m_buffer);
}
size_t MyString::size()const{
return m_size;
}
size_t MyString::length(){
return strlen(m_buffer)-1;
}
const char* MyString::c_str() const {
char *str = NULL;
str = new char[m_size];
for(size_t i = 0; i < m_size;i++){
str[i] = *(m_buffer+i);
}
return str;
delete [] str;
str = NULL;
}
bool MyString::operator==(const MyString & other)const{
if(strcmp(m_buffer,other.m_buffer) == 0){
return true;
}else if (strcmp(m_buffer,other.m_buffer) != 0){
return false;
}
}
MyString & MyString::operator=(const MyString & str1){
buffer_deallocate();
m_buffer = new char[str1.m_size];
strcpy(m_buffer,str1.m_buffer);
}
MyString MyString::operator+(const MyString & other_myStr)const{
MyString myStr(strcat(m_buffer,other_myStr.m_buffer));
return myStr;
}

String class istream issues

I am having trouble getting my string class working. My istream function seems to read the data in, and I confirmed that the += was adding the characters, but after the first character, what is added is garbage. I have tried everything I can think of to get it working. Can someone please provide some insight as to what is going wrong. Thanks.
istream& operator >>(istream& ins, string& target)
{
char newInput;
while (ins && isspace(ins.peek()))
ins.ignore();
target = ("");
//int count = 0;
while (ins && !isspace(ins.peek())) //(ins.peek())))
{
ins >> newInput;
target.operator+=(newInput);
}
return ins;
}
void string::operator +=(char addend)
{
if (this->current_length + 1 > this->allocated)
{
reserve(allocated + 1);
}
sequence[current_length] = addend;
current_length += 1;
}
void string::reserve(size_t n)
{
assert(n > current_length);
char *newSequence = new char[n];
if (n == allocated)
{
return;
}
for (size_t i = 0; i < n; i++)
{
newSequence[i] = sequence[i];
}
//destroy old array
delete[] sequence;
//update capacity
allocated = n;
//point data at new array
sequence = newSequence;
}
Full Code: **
#pragma warning(disable : 4996)
#ifndef MAIN_SAVITCH_CHAPTER4_MYSTRING_H
#define MAIN_SAVITCH_CHAPTER4_MYSTRING_H
#include <cstdlib> // Provides size_t
#include <cassert>
#include <string.h>
#include <iostream>
#include <ctype.h>
#include <algorithm>
using namespace std;
namespace main_savitch_4
{
class string
{
public:
// CONSTRUCTORS and DESTRUCTOR
string(const char str[] = "");
string(const string& source);
~string() { delete[] sequence; }
// MODIFICATION MEMBER FUNCTIONS
void operator +=(const string& addend);
void operator +=(const char addend[]);
void operator +=(char addend);
void reserve(size_t n);
void operator =(const string& source);
// CONSTANT MEMBER FUNCTIONS
size_t length() const { return current_length; }
char operator [ ](size_t position) const;
// FRIEND FUNCTIONS
friend ostream& operator <<(ostream& outs, const string& source);
friend bool operator ==(const string& s1, const string& s2);
friend bool operator !=(const string& s1, const string& s2);
friend bool operator >=(const string& s1, const string& s2);
friend bool operator <=(const string& s1, const string& s2);
friend bool operator > (const string& s1, const string& s2);
friend bool operator < (const string& s1, const string& s2);
private:
char *sequence;
size_t allocated;
size_t current_length;
};
// CONSTRUCTOR for the string class:
// string(const char str[ ] = "") -- default argument is the empty string.
// Precondition: str is an ordinary null-terminated string.
// Postcondition: The string contains the sequence of chars from str.
string::string(const char str[])
{
current_length = strlen(str);
allocated = current_length + 1;
sequence = new char[allocated];
for (size_t i = 0; i < allocated; i++)
{
sequence[i] = str[i];
}
}
string::string(const string& source)
//copy constructor
{
current_length = source.current_length;
allocated = current_length + 1;
sequence = new char[allocated];
for (size_t i = 0; i < allocated; i++) {
sequence[i] = source.sequence[i];
}
}
//~string();
// CONSTANT MEMBER FUNCTIONS for the string class:
// size_t length( ) const
// Postcondition: The return value is the number of characters in the
// string.
//
// char operator [ ](size_t position) const
// Precondition: position < length( ).
// Postcondition: The value returned is the character at the specified
// position of the string. A string's positions start from 0 at the start
// of the sequence and go up to length( )-1 at the right end.
char string::operator [ ](size_t position) const
{
assert(position < length());
return (sequence[position]);
}
// MODIFICATION MEMBER FUNCTIONS for the string class:
// void operator +=(const string& addend)
// Postcondition: addend has been catenated to the end of the string.
//
void string::operator =(const string& source)
{
//string assigned to self
if (sequence == source.sequence)
{
return;
}
if (source.current_length > this->allocated)
reserve(source.current_length);
delete[] sequence;
current_length = source.current_length;
allocated = current_length + 1;
for (size_t i = 0; i < allocated; i++) {
sequence[i] = source.sequence[i];
}
}
void string::operator +=(const string& addend)
{
if (this->current_length + addend.current_length > this->allocated)
{
reserve(current_length + addend.allocated);
}
//copy addend to sequence
for (size_t i = 0; i < addend.current_length; i++)
{
sequence[i + current_length] = addend.sequence[i];
}
current_length = current_length + addend.current_length;
}
// void operator +=(const char addend[ ])
// Precondition: addend is an ordinary null-terminated string.
// Postcondition: addend has been catenated to the end of the string.
void string::operator +=(const char addend[])
{
if (this->current_length + strlen(addend) > this->allocated)
reserve(current_length + strlen(addend));
//copy addend to sequence
for (size_t i = 0; i < strlen(addend); i++)
{
sequence[i + current_length] = addend[i];
}
current_length += strlen(addend);
}
// void operator +=(char addend)
// Postcondition: The single character addend has been catenated to the
// end of the string.
//
void string::operator +=(char addend)
{
if ((this->current_length + 1) > (this->allocated))
{
reserve(allocated + 1);
}
//copy addend to sequence
sequence[current_length] = addend;
current_length += 1;
}
// void reserve(size_t n)
// Postcondition: All functions will now work efficiently (without
// allocating new memory) until n characters are in the string.
void string::reserve(size_t n)
{
assert(n > current_length);
//create new array
char *newSequence = new char[n];
if (n == allocated)
{
return;
}
if (n < current_length + 1)
{
n = current_length + 1;
}
for (size_t i = 0; i < current_length; i++)
{
newSequence[i] = sequence[i];
}
delete[] sequence;
//update capacity
allocated = n;
//point data at new array
sequence = newSequence;
}
//Friend Functions
bool operator ==(const string& s1, const string& s2)
{
return (s1 == s2);
}
bool operator !=(const string& s1, const string& s2)
{
return !(s1 == s2); //(strcmp(s1.sequence, s2.sequence) == 0);
}
bool operator >=(const string& s1, const string& s2)
{
return (s1 >= s2); //(strcmp(s1.sequence, s2.sequence) >= 0);
}
bool operator <=(const string& s1, const string& s2)
{
return (s1 <= s2); //(strcmp(s1.sequence, s2.sequence) <= 0);
}
bool operator > (const string& s1, const string& s2)
{
return (s1 > s2); //(strcmp(s1.sequence, s2.sequence) > 0);
}
bool operator < (const string& s1, const string& s2)
{
return (s1 < s2); // (strcmp(s1.sequence, s2.sequence) < 0);
}
// NON-MEMBER FUNCTIONS for the string class
// string operator +(const string& s1, const string& s2)
// Postcondition: The string returned is the catenation of s1 and s2.
//
string operator +(const string& s1, const string& s2)
{
string temp = s1;
temp = s1 + s2;
return temp;
}
// istream& operator >>(istream& ins, string& target)
// Postcondition: A string has been read from the istream ins, and the
// istream ins is then returned by the function. The reading operation
// skips white space (i.e., blanks, newlines, tabs) at the start of ins.
// Then the string is read up to the next white space or the end of the
// file. The white space character that terminates the string has not
// been read.
//
istream& operator >>(istream& ins, string& target)
{
char newInput;
while (ins && isspace(ins.peek()))
ins.ignore();
target = ("");
while (ins && !isspace(ins.peek())) //(ins.peek())))
{
ins >> newInput;
cout << newInput;
target.operator+=(newInput);
}
return ins;
}
// ostream& operator <<(ostream& outs, const string& source)
// Postcondition: The sequence of characters in source has been written
// to outs. The return value is the ostream outs.
ostream& operator <<(ostream& outs, const string& source)
{
outs << source.sequence;
return outs;
}
//
// void getline(istream& ins, string& target, char delimiter)
void getline(istream& ins, string& target, char delimiter)
{
{
int count = 0;
char newLine;
while (ins)
{
ins.get(newLine);
target.operator+=(newLine);
}
}
}
}
#endif
#pragma once
The new[] and delete[] must be balanced.
The string::operator=(const string&) routine is delete[] the sequence array, which later gets delete[] again in the reserve routine.
while (ins && !isspace(ins.peek())) //(ins.peek())))
{
ins >> newInput;
target.operator+=(newInput);
}
Here you:
Check whether the stream has had any errors or attempted to read past the end
Extract the next character, assume this succeeded, then see whether it's a space
Read said character, and again assume this succeeded — if it did, it is assigned to newInput
Insert the contents of newInput to target (with a direct function call for some reason)
If the next read fails, you have no checking of that, and newInput isn't what you think it is.
You've only checked for errors before doing a thing.
Perhaps something like this would better suit:
while (true) {
const auto next = ins.peek();
if (!ins) break;
if (isspace(next)) break;
ins >> newInput;
target += newInput;
}
I'm assuming that if the peek succeeded then the >> will also, but in practice I'd probably put another check for !ins before the target += line, unless I were concerned about speed. In particular, you should double-check whether peek() sets eofbit, because I can't remember and, if it doesn't, you'll definitely need another if.

What's wrong with my String concatenation in C++?

I am learning C++ by creating a String class for an embedded project and I have a problem with my String class' concatenation.
Here is my main method and the output
#include <iostream>
#include "string.hpp"
using namespace std;
int main() {
String s1("hello "), s2("world");
String s3 = s1 + s2;
cout << "s1=" << s1 << endl;
cout << "s2=" << s2 << endl;
cout << "s3=" << s3 << endl;
return 0;
}
s1=hello
s2=world
s3=hello
Rather than print out "hello world", it prints just "hello "
Here is my string.hpp class:
#pragma once
#include <cstring>
#include <iostream>
class String {
public:
String() : c_str(NULL), len(0)
{
}
String(const String& str) : c_str(new char[str.len]), len(str.len)
{
strncpy(c_str, str.c_str, len);
c_str[len] = '\0';
}
String(const char* str) : String(str, strlen(str))
{
strncpy(c_str, str, len);
c_str[len] = '\0';
}
String(const char* str, const int n) : len(n), c_str(new char[n+1])
{
strncpy(c_str, str, len);
}
~String()
{
delete[] c_str;
}
const char* get_c_str()
{
return c_str;
}
bool contains(const String &cmd, const size_t pos)
{
return strncmp(c_str+pos, cmd.c_str, cmd.len) == 0;
}
size_t length()
{
return len;
}
friend std::ostream& operator<<(std::ostream& os, const String obj)
{
os << obj.c_str;
return os;
}
friend void swap(String& s1, String& s2)
{
using std::swap;
swap(s1.c_str, s2.c_str);
swap(s1.len, s2.len);
}
bool operator==(const String& str)
{
return strncmp(c_str, str.c_str, len) == 0;
}
char operator[](const size_t i)
{
return c_str[i];
}
String& operator=(const String& src)
{
String tmp(src);
swap(*this, tmp);
return *this;
}
String operator+(const String& rhs)
{
const size_t new_len = len + rhs.len;
char* new_c_arr = new char[new_len+1];
strcpy(new_c_arr, c_str);
strcat(new_c_arr, rhs.c_str);
printf("new_c_arr=%s\n", new_c_arr);
return String(new_c_arr, len);
}
String operator+(const char* rhs)
{
const size_t new_len = len + strlen(rhs) + 1;
char* new_c_arr = new char[new_len];
strcpy(new_c_arr, c_str);
strcat(new_c_arr, rhs);
return String(new_c_arr, new_len);
}
private:
char* c_str;
int len;
};
I read about "the big 3" on SO while looking for a similar question and not sure if it because of this.
This code is broken in numerous ways.
#pragma once
Actual include guards are more portable than #pragma once.
String() : c_str(NULL), len(0)
{
}
Your default constructor makes c_str null; your other functions never check for this case. Remember that even an empty C string has one character.
String(const String& str) : c_str(new char[str.len]), len(str.len)
{
strncpy(c_str, str.c_str, len);
c_str[len] = '\0';
}
You only allocated str.len characters for c_str, yet you are accessing c_str[len].
String(const char* str) : String(str, strlen(str))
{
strncpy(c_str, str, len);
c_str[len] = '\0';
}
The constructor to which you delegated already performed a copy. Why are you calling strncpy here again?
String(const char* str, const int n) : len(n), c_str(new char[n+1])
{
strncpy(c_str, str, len);
}
and here you didn't make sure that your string is null-terminated.
const char* get_c_str()
{
return c_str;
}
Should be marked const.
bool contains(const String &cmd, const size_t pos)
{
return strncmp(c_str+pos, cmd.c_str, cmd.len) == 0;
}
Ditto. And you didn't check that pos is in range.
size_t length()
{
return len;
}
const.
friend std::ostream& operator<<(std::ostream& os, const String obj)
{
os << obj.c_str;
return os;
}
obj should be passed by const reference, not by value.
bool operator==(const String& str)
{
return strncmp(c_str, str.c_str, len) == 0;
}
const again, and the logic isn't even correct. By this logic, "something" == "something else" since you are only comparing the first len characters.
char operator[](const size_t i)
{
return c_str[i];
}
If you are returning a copy, then it should be const. If you want to allow users to modify the characters stored in the string, then it should return a char &. (Even better, have two separate overloads, one const and one non-const.)
String operator+(const String& rhs)
{
const size_t new_len = len + rhs.len;
char* new_c_arr = new char[new_len+1];
strcpy(new_c_arr, c_str);
strcat(new_c_arr, rhs.c_str);
printf("new_c_arr=%s\n", new_c_arr);
return String(new_c_arr, len);
}
You are constructing the new string with the wrong length, and also leaking new_c_arr. And this function should be const (and really should be implemented in terms of operator+=, which you don't have).
String operator+(const char* rhs)
{
const size_t new_len = len + strlen(rhs) + 1;
char* new_c_arr = new char[new_len];
strcpy(new_c_arr, c_str);
strcat(new_c_arr, rhs);
return String(new_c_arr, new_len);
}
Leaking new_c_arr again; also, new_len here includes the null terminator, while the version in the other operator+ doesn't. Your constructor taking a length does not appear to include the null terminator as part of the length.
This is the line of problem in the method String operator+(const String& rhs):
return String(new_c_arr, len);
You need to changed to this:
return String(new_c_arr, new_len+1);
You are initializing the returning String with a length equal to the first part only. Not the whole concatenated string.
See that the other operator is OK.
By the way you're creating a lot of new char[] in the operator+ and the constructor.
In the case of the operator+ you are creating a new char[] in every call and passing to the constructor of string (not deleting after), and in the constructor are creating a new char[] to storage the string that is deleted in the destructor, the new char[] created in the operators are leaked.

Overloading operator new / allocate more than object size

I'm trying to overloading the operator new of my class, I wanna allocate space for the objects' attributes and for a vector of chars that isn't defined in the class.
But when I instance an new object, the chars of previously object are changing.
Am I doing something wrong?
class StringData
{
public:
friend class String;
int refCount;
int len;
int maxLen;
~StringData()
{
}
StringData()
{
maxLen = 1000;
len = 0;
refCount = 1;
}
StringData(const char * string)
{
maxLen = 1000;
char * data = buffer();
len = 0;
while (string[len] != '\0' && len < (maxLen - 1))
{
data[len] = string[len];
len++;
}
data[len] = '\0';
refCount = 1;
}
char* buffer()
{
return reinterpret_cast<char*>(this + 12);
}
public:
void* operator new(size_t size, int maxLen)
{
return ::operator new(size + round4(maxLen + 1));
}
static int round4(int len)
{
return ((((int) (len / 4)) + 1) * 4);
}
void operator delete(void* obj)
{
::operator delete(obj);
}
void operator delete(void* obj, int size) throw ()
{
::operator delete(obj);
}
};
I use this in other class:
class String{
public:
StringData * data;
String(StringData * data){
this->data = data;
}
public:
String(const char*);
String(const String&);
~String();
String& operator =(const String);
String& operator =(const char *);
int length() const;
bool operator ==(const String&) const;
int compare(const String&) const;
bool operator ==(const char*) const;
int compare(const char*) const;
String& operator +(const String&) const;
String operator +(const char*) const;
String operator +=(const String&);
String operator +=(const char*);
String toLower();
String toUpper();
char operator [ ](int) const;
char& operator [ ](int);
void print() const;
};
String::String(const char * string){
int stringLen = 0;
while (string[stringLen] != '\0')
stringLen++;
data = new (stringLen + 1) StringData(string);
}
String::String(const String& string){
data = string.data;
string.data->refCount++;
}
String::~String(){
this->data->refCount--;
if (this->data->refCount == 0)
delete data;
}
String& String::operator=(const String string){
data->refCount--;
if (this->data->refCount == 0)
delete data;
data = string.data;
string.data->refCount++;
return *this;
}
void String::print() const{
printf("%s\n", data->buffer());
}
And my main function is:
int main(){
String *a = new String("boisahzashdacaraverdeepretaeazuleamarelaecinzaevermelha");
a->print();
String * s = new String("freestepehnoisquevoaashashashhasshashhasssasassadasd");
String * b = new String("kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk");
a->print();
s->print();
return 0;
}
When I execute, the strings are broken:
boisahzashdacaraverdeepretaeazuleamarelaecinzaevermelha
boisahzashdacaraverd
freestepehnoisquevoa
This is not a great idea:
return reinterpret_cast<char*>(this + 12);
Not only does it fail if you ever add/remove some member functions [or make a virtual function], but it's also dependent on the size of int.
Use
return reinterpret_cast<char*>(this) + sizeof(*this);
[Note newplacement of the end of reinterpret_cast<>()!!]
The first version skips 12 * sizeof(*this) forwards, rather than 12 bytes.
[Of course, on my machine, when I used the 4* multiplier of maxLen, it actually works - it only began failing when I removed that]
This can be simplified:
((((int) (len / 4)) + 1) * 4);
Is this supposed to be 4 times larger than maxlen:
(4 * maxLen)
to:
4 * (len / 4 + 1);
I will be back with edits to this answer once I know the answer to the comment about how it is being tested.