Deconstruct const pointer? - c++

It's probably very basic but I am stuck and simply don't know what the problem is.
The main code is predefined as a task. The goal is to use const as much as possible. The following constructor is just supposed to copy the literal string to the const m_data and that works fine but I am not able to free the memory - it always leaves 1 block. What am I missing?
main.cpp
#include <iostream>
#include "immstring.hpp"
using namespace std;
using namespace Util;
int main()
{
const ImmutableString s1("Hello");
}
immu.hpp
#include <cstring>
namespace Util {
class ImmutableString {
public:
ImmutableString(const char* src);
~ImmutableString();
private:
char* const m_data;
};
}
immu.cpp
#include "immstring.hpp"
#include <iostream>
#include <cstring>
namespace Util
{
ImmutableString::ImmutableString(const char* src)
:m_data{strcpy(new char[strlen(src)+1],src)}{}
ImmutableString::~ImmutableString()
{
delete m_data;
}
}

To leave all array memories blocks you have to use delete like this :
delete[] m_data;
Thanks,
Robin.

Related

assignment operator error in unique pointer

I tried to use unique_ptr in c++ in a singelton pattern instead of raw pointer. when I want to assign a unique_ptr to another I got an error. I tried to use std::move to assign but it did not work. the code is as follow:
#include <iostream>
#include <memory>
#include <list>
#include <algorithm>
#include <iterator>
#include <string>
using namespace std;
class ClientDB
{
private:
static unique_ptr<ClientDB> theDB;
ClientDB() {}
list<string> clients;
public:
~ClientDB() {}
static unique_ptr<ClientDB> getInstance()
{
if(theDB==nullptr)
theDB = make_unique<ClientDB>;
return theDB;
}
void addClient(string c) {clients.push_back(c);}
void printClients(ostream& os)
{
copy(clients.cbegin(),clients.cend(),ostream_iterator<string>{os,"\n"});
}
};
int main()
{
unique_ptr<ClientDB> db1{ClientDB::getInstance()};
db1->addClient("Mr. Schultz");
unique_ptr<ClientDB> db2{ClientDB::getInstance()};
db2->addClient("Mrs. James");
unique_ptr<ClientDB> db3{ClientDB::getInstance()};
db3->addClient("Mr. Karajan");
db1->printClients(cout);
}
and the error I got is
error: no match for ‘operator=’ (operand types are ‘std::unique_ptr<ClientDB>’ and ‘<unresolved overloaded function type>’)
theDB = make_unique<ClientDB>;
and another question is if nullptr can be used for unique_ptr.
Finally by help of my teacher, I can solve the problem. there is some points should be considered.
1- for unique_ptr assignment, std::move:: should be used.
2- make_unique has no access to the private constructor, the constructor should be called explicitly:
theDB = unique_ptr<ClientDB>(new ClientDB());
3-The unique-ptr must be initialized outside the class:
unique_ptr<ClientDB> ClientDB::theDB;
4- Three unique pointers in main for the same object can not be used, only one is allowed for uniqueness. references to unique_ptr should be used instead:
unique_ptr<ClientDB>& db1=ClientDB::getInstance();
and finally the code should be like this
#include <iostream>
#include <memory>
#include <list>
#include <algorithm>
#include <iterator>
#include <string>
using namespace std;
class ClientDB
{
private:
static unique_ptr<ClientDB> theDB;
ClientDB() {}
list<string> clients;
public:
~ClientDB() {}
static unique_ptr<ClientDB>& getInstance()
{
if(theDB==nullptr)
//theDB = move(make_unique<ClientDB>());
theDB = unique_ptr<ClientDB>(new ClientDB());
return theDB;
}
void addClient(string c) {clients.push_back(c);}
void printClients(ostream& os)
{
copy(clients.cbegin(),clients.cend(),ostream_iterator<string>{os,"\n"});
}
};
unique_ptr<ClientDB> ClientDB::theDB;
int main()
{
unique_ptr<ClientDB>& db1=ClientDB::getInstance();
db1->addClient("Mr. Schultz");
unique_ptr<ClientDB>& db2=ClientDB::getInstance();
db2->addClient("Mrs. James");
unique_ptr<ClientDB>& db3=ClientDB::getInstance();
db3->addClient("Mr. Karajan");
db1->printClients(cout);
}

how to use pointer to ostream in class

I need ostream pointer in class which will be created at the time of construction of class.
My code is :
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <cstring>
#include <climits>
#include <cstdio>
#include <fstream>
using namespace std;
class test2_t {
public:
test2_t ()
{
std::filebuf fb;
fb.open ("dump.txt",std::ios::out);
ostream *output_ = new std::ostream(&fb);
}
virtual ~test2_t ()
{}
ostream *output_;
void printing()
{
print(output_);
}
void print(ostream *out)
{
*out<<"dump data"<<"\n";
}
private:
/* data */
};
int main( )
{
test2_t obj;
obj.printing();
}
But is getting Segmentation fault I don't know why. Please help me out.
You made the following mistake in your code:
You "redeclared" your "Output"-variable in the constructor - so the pointer ios only stored in a local variable within the constructor-scope.
change this line: ostream *output_ = new std::ostream(&fb);
into: *output_ = new std::ostream(&fb);
In this way, the member-variable of your class is filled with the correkt pointer.
You can change your construtor function like follows to get it working:
test2_t () : output_(new std::ofstream("dump.txt")) {
}
Don't forget to release the resource in the destructor:
virtual ~test2_t () {
delete output_;
}

C++ unique_ptr and arrays

I'm trying to use arrays with unique_ptr with no success.
What is the correct way to declare a unique_ptr of some size?
(size is some paramter).
unique_ptr<A[]> ptr = make_unique<A[]>(size);
Here's an example:
#include <iostream>
#include <string>
#include <vector>
#include <functional>
#include <memory>
using namespace std;
class A {
string str;
public:
A(string _str): str(_str) {}
string getStr() {
return str;
}
};
int main()
{
unique_ptr<A[]> ptr = make_unique<A[]>(3);
}
This is not working, however, if I delete the constructor of A, it works.
I want the 3 to represent the size of the array, and not an argument to A's constructor, how do I make that happen?
This is not working, however, if I delete the constructor of A, it
works.
When you removed the user defined constructor, the compiler implicitly generates a default one. When you provide a user defined constructor, the compiler doesn't implicitly generate a default constructor.
std::make_unique<T[]> requires the use of default constructors...
So, provide one, and all should work well
#include <iostream>
#include <string>
#include <vector>
#include <functional>
#include <memory>
using namespace std;
class A {
string str;
public:
A() = default;
A(string _str): str(_str) {}
string getStr() {
return str;
}
};
int main()
{
unique_ptr<A[]> ptr = make_unique<A[]>(3);
}

C++ Templates specialisation char* and Valgrind

I've got a huge problem with memory leaks in my program.
I use Valgrind to check memory leaks and with some changes I got about ~20 errors or ~40 errors, but still I can't eliminate all and don't know how.
And I can't change the code in main function, I must fit to it.
I can't change specialisation to string!
Question is what is a properly way to manage with char* and memory.
Rules:
Main code is unchangable
Don't pack char* in any smart pointers or other types.
Problem
Managing memory with char* with containers.
Is it still possible ?
Or instead of container safer is normally allocated array ?
What is wrong with my destructor for char* ?
My main function:
#include <iostream>
#include "test.h"
#include <vector>
using namespace std;
int main()
{
char * cpt[]={"tab","tab2","tab3"};
test<char*> test1;
test1.addItem(cpt[1]);
char * item=test1.getItem(0);
item[0]='Z';
cout<<item<<endl;
return 0;
}
test.h
#ifndef TEST_H
#define TEST_H
#include <vector>
using namespace std;
template<class T>
class test
{
public:
~test();
void addItem(T element){
elements.push_back(element);
}
T getItem(int i){
return elements[i];
}
vector<T> elements;
};
#endif // TEST_H
test.cpp
#include "test.h"
#include <iostream>
#include <cstring>
using namespace std;
template<>
char * test<char*>::getItem(int i)
{
/*char *nowy=new char(strlen(elements[i])+1);
//strcpy(nowy,elements[i]);
return nowy;
//with above code 39 errorr in Valgrind
*/
return elements[i]; // with this instead of above 19 errors in Valgrind
}
template<>
void test<char*>::addItem(char* element){
char * c= new char( strlen (element)+1);
strcpy(c,element);
elements.push_back(c);
}
template<>
test<char*>:: ~test(){
for( auto v: elements)
delete []v; //with this 20 errors
//delete v; instead of above line 19 errors;
}
You should replace
new char(strlen (element) + 1); // this allocate one char with given initial value
by
new char[strlen (element) + 1]; // array of (uninitialized) char
to allocate array of char.
then you have to call delete [].

implementing map<mpz_t, double> in c++

For some reason, I need to have a map from arbitrary huge number to double and I tried to implement it with c++98 (and I have to) and Xcode but it doesn't work:
#include <iostream>
#include <string>
#include <map>
#include <vector>
#include <set>
#include "gurobi_c++.h"
#include <sstream>
#include "boost/tuple/tuple.hpp"
#include "boost/tuple/tuple_comparison.hpp"
#include "boost/tuple/tuple_io.hpp"
#include <cmath>
#include <gmp.h>
using namespace std;
using namespace ::boost::tuples;
using namespace ::boost;
int main()
{
map<mpz_t, double>J;
mpz_t a,b,c,n;
string tempstring;
int xrange=5,yrange=5,component=5;
mpz_set_str(n,"11", 10);
J[n]=-1;
return 0;
}
The error shown is: Array initializer must be an initializer list. Could someone help me with it? Thank you:)
Here's the detail error page:
I don't know the details of mpz_t. However, it appears to be an array.
You can get around the problem by defining a class to be used as the key in your map.
I am able to create an executable using the following code with g++ 4.8.2.
#include <map>
using namespace std;
typedef int (mpz_t)[2];
struct MyKey
{
// Add a proper implementation of a constructor
// with mpz_t.
MyKey(mpz_t in) {}
// Add a proper implementation of copy constructor.
MyKey(MyKey const& copy) {}
// Add a proper implementation of assignment operator.
MyKey& operator=(MyKey const& rhs)
{
return *this;
}
bool operator<(MyKey const& rhs) const
{
// Add a proper implementation.
return false;
}
mpz_t n;
};
int main()
{
map<MyKey, double> J;
mpz_t n;
J[n] = 1.0;
return 0;
}