Class to manage pointers better: some errors


I wrote a class to manage pointers better (because I am making a large program and don't want to call a constructor on somthing that was already deleted... etc...), but I am getting some compiler errors. I'm not sure what to do.

here is the class prototype:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
template<typename type>
class pointer_class{
public:
    
    pointer_class() : dat(NULL), del(false) {}
    
    explicit pointer_class(const pointer_class<type>& d) : dat(NULL), 
            del(d.del) {
        if(del)
        {
            this->dat = new type(*d.dat);
        }
        if(!del)
        {
            this->dat = d.dat;
        }
    }
    
    explicit pointer_class(type* d) : dat(d), del(true) {}
    
    explicit pointer_class(type& d) : dat(&d), //error here (invalid conversion??)
            del(false) {}
    
    ~pointer_class()
    {
        if(del)
        {
            delete dat;
        }
    }
    
    bool operator==(const pointer_class& d)
    {
        return (*(d.dat) == *(this->dat));
    }
    
    pointer_class<type> operator=(const type& d)
    {
        *this = pointer_class(d);
        return *this;
    }
    
    /* Allows modification of dat, as well as access to member functions, 
     * but not the pointer. */
    type& gdata()
    {
        return *(this->dat);
    }
    
    type gdata_const() const
    {
        return *(this->dat);
    }
    
private:
    type *dat;
    const bool del;
    
};


Here are the compiler errors:

path_selection_class.h: In member function 'path_selection_class& path_selection_class::operator=(const path_selection_class&)':
In file included from browse_filesystem.cpp:16:0:
path_selection_class.h:32:25: error: use of deleted function 'pointer_class<std::vector<std::basic_string<char> > >& pointer_class<std::vector<std::basic_string<char> > >::operator=(const pointer_class<std::vector<std::basic_string<char> > >&)'
             this->paths = s.paths;
                         ^
In file included from vector_display_buff.h:13:0,
                 from browse_filesystem.cpp:10:
pointer_class.h:16:7: note: 'pointer_class<std::vector<std::basic_string<char> > >& pointer_class<std::vector<std::basic_string<char> > >::operator=(const pointer_class<std::vector<std::basic_string<char> > >&)' is implicitly deleted because the default definition would be ill-formed:
 class pointer_class{
       ^
pointer_class.h:16:7: error: non-static const member 'const bool pointer_class<std::vector<std::basic_string<char> > >::del', can't use default assignment operator
pointer_class.h: In instantiation of 'pointer_class<type>::pointer_class(const type&) [with type = std::vector<std::basic_string<char> >]':
path_selection_class.h:18:19:   required from here
pointer_class.h:27:22: error: invalid conversion from 'const std::vector<std::basic_string<char> >*' to 'std::vector<std::basic_string<char> >*' [-fpermissive]
             del(false) {}
                      ^


I can not think of any way to solve this issue... I added a copy constructor, but alas, I have not been successful.

Thanks for your help.
Last edited on
I fixed the larger issues, but I can't get this out of the way:

I modified the copy-constructor, now the pointer is directly copied (don't know why I didn't think of that before...):

1
2
3
4
5
6
7
8
9
10
11
explicit pointer_class(const pointer_class<type>& d) : dat(NULL), 
            del(d.del) {
        if(del)
        {
            this->dat = new type(*d.dat);
        }
        if(!del)
        {
            this->dat = d.dat;
        }
    }


now I am still getting these errors:

path_selection_class.h: In member function 'path_selection_class& path_selection_class::operator=(const path_selection_class&)':
In file included from browse_filesystem.cpp:16:0:
path_selection_class.h:32:25: error: use of deleted function 'pointer_class<std::vector<std::basic_string<char> > >& pointer_class<std::vector<std::basic_string<char> > >::operator=(const pointer_class<std::vector<std::basic_string<char> > >&)'
             this->paths = s.paths;
                         ^
In file included from vector_display_buff.h:13:0,
                 from browse_filesystem.cpp:10:
pointer_class.h:16:7: note: 'pointer_class<std::vector<std::basic_string<char> > >& pointer_class<std::vector<std::basic_string<char> > >::operator=(const pointer_class<std::vector<std::basic_string<char> > >&)' is implicitly deleted because the default definition would be ill-formed:
 class pointer_class{
       ^
pointer_class.h:16:7: error: non-static const member 'const bool pointer_class<std::vector<std::basic_string<char> > >::del', can't use default assignment operator
Last edited on
Sounds like you are writing a smart pointer, why not use the ones in the std?
http://www.cplusplus.com/reference/memory/unique_ptr/
http://www.cplusplus.com/reference/memory/shared_ptr/
Because I don't want to. I want to do somthin specific.

Also, i recognize this problem revolves around the fact I can't modify a const member variable of the class without an initializer list (am I wrong??), so is there some way to do this?
Make the member variable non-const. Because it is private, you can determine if and when it is modified.
closed account (o1vk4iN6)
Why create a pointer class for a std::vector ? That is basically a class with just a pointer.
ah, I fixed it. I kept the member var const, and created a copy-operator. I have the bool const because it should NEVER EVER change between instances of the class. However, I want to be able to make one equal to another (which means deleting memory if it was allocated to the class, and re-assigning al the variables), so I thought I could not use the operator. I can though.


The modified class looks like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
template<typename type>
class pointer_class{
public:
    
    pointer_class() : dat(NULL), del(false) {}
    
    explicit pointer_class(type* d) : dat(d), del(true) {}
    
    explicit pointer_class(const type& d) : dat(&d), 
            del(false) {}
    
    ~pointer_class()
    {
        if(del)
        {
            delete dat;
        }
    }
    
    /* Returns boolean operator on the data pointed
     to by dat.*/
    bool operator==(const pointer_class<type>& d)
    {
        return (*(d.dat) == *(this->dat));
    }
    
    /* Makes pointer point to d.  Does not delete the
     data that d stores. */
    pointer_class<type> operator=(const type& d)
    {
        *this = pointer_class(d);
        return *this;
    }
    
    pointer_class<type> operator=(const pointer_class<type>& d)
    {
        if(this->del)
        {
            delete this->dat;
        }
        if(!d.del)
        {
            this->dat = d.dat;
        }
        if(d.del)
        {
            *(this->dat) = *(d.dat);
        }
        this->del = d.del;
        return *this;
    }
    
    /* Allows modification of dat, as well as access to member functions, 
     * but not the pointer. */
    type& gdata()
    {
        return *(this->dat);
    }
    
    type gdata_const() const
    {
        return *(this->dat);
    }
    
private:
    type *dat;
    bool del;
    
};


Works like a charm. Thanks for the help.
Last edited on
@xerzi
It's not just for std::vector, he's just instantiating it with type=std::vector<std::string>

@IWishIKnew
From the errors it looks like you need to explicitly define your assignment operator pointer_class<T> operator=(const pointer_class<T>&);

and as doug4 said remove the const from del.
@xerzi
Not just for vector: for any variable type. I want to be able to create pointers, without warping my train of though by trying to figure out if a variable allocated new space, or just pointes to somthing that already exists. With this class, all I have to do is assign a variable using the new declaration with the constructor call of the object.

Example of emplementation:

1
2
3
4
5
6
//I want to create a string:
pointer_class<string> mystring(new string("Hello World!!"));

//what if I want to use the member of another class, but dont want to copy EVERYTHING??
string my_long_string("whatever...");
pointer_class<string> a_copy(my_long_string); //a_copy points to, and directly modifies, my_long_string 


The whole reason I wanted to make this class was because I am emplementing an object oriented design for a very larg program I'm creating. I do not want to copy, say, a vector of 2,000 strings just to save it as a group to a file.
Last edited on
1
2
3
4
int x = 5;
{
     pointer_class<int> xptr(&x);
}

What happens at line 4?

1
2
3
4
5
6
7
int* x = new int(5);
int y = 7;
{
    pointer_class<int> xptr(x);
    pointer_class<int> xptr(y);
    xptr = yptr;
}


When does the memory allocated in line 1 get freed?
Where are you writing xptr.dat in line 43 of your code?

Edit:

You've got the right idea, but you really need to pay attention to when you are deleting things. Your code may work like a charm the way you are currently using it, but there a number of holes that could get you into trouble.
Last edited on
@doug4:

The class is not meant for that. Never pass the address of an existing variable, only the variable itself (and it's address will be taken by the class). That instance is undefined.

As for your second example, the space will not be freed by the class, but by the deconstruction of the object that holds the information. Note that if the class was to delete data stored in x or y, then when their respective deconstructors are called, they would try to de-allocate space that was already deallocated by my class.

@doug:
xptr.dat... what is that supposed to be? This is in C++.

Also, I know: passing a pointer to it, then deleteing the pointer and calling the deconstructor. But that's not the reason I added that constructor: I added it so that the pointer could allocate new space and act as a new variable, and not point to another, independent variable. If you have a better suggestion, I will listen.

****************************************************************
Also, to anyone else who has any way to improve this class, please let me know.
Last edited on
closed account (o1vk4iN6)
Pretty obvious it is not just for vector but his code is using it as such merely pointing out the redundancy of using it with said class.

Your operator= should be re piturning a reference not a new copy as well.

/what if I want to use the member of another class, but dont want to copy EVERYTHING??

That's what a reference is for...
Last edited on
Alright.

Also, what do you mean by "the redundancy of useing it with said class"?

Also, if I pass a reference, then I am just initializing a pointer with the address... otherwise, I don't see any way to assign a variable's address.... Unless you know a way...

1
2
3
4
5
6
7
8
class myclass{

public:
    myclass(const int& i) : x(i) {} //passing by reference, but we are still copying the variable to x...

private:
     int x;
};


@doug:

Would you like to help me fill them??
Last edited on
closed account (o1vk4iN6)
You are doing it in your pointer_class ...

1
2
3
4
5
6
7
8
9
10
11
12
class myclass
{
public:

    myclass(int& i) : x(&i) { } // worse
    myclass(int* i) : x(i) { } // better

private:

    int* x;

};

I don't think it is wise to pass an object by reference and then retain that object. It'd be better to do it by a pointer so that the user knows explicitly that they are giving an object a pointer to it which it could potentially store it for use later.

If you plan on using the same resource across multiple classes consider looking into std::shared<>, that way the lifetime of the object would be guaranteed. It really depends on what you are doing, for instance:
I do not want to copy, say, a vector of 2,000 strings just to save it as a group to a file

i don't see why you can't just pass the vector by reference to a function that would then save it to a file, though your chose of wording makes your statement very unclear as to what you are doing.
Last edited on
ok, I have an example:

A user selects a group of filesystem directories, and chooses to save them into a group of favorites.

Which is better:

A: copy the entire list (duplicating it) into the class, which will process, and add it, into a group in the favorites list

or

B: create a pointer, and just directly reference the list, not allocating any new space that we don't need to, then immediately save the new group and destroy the list.

Better yet, I could add a member function to the class to add on the list without takeing anything out of the file, but the point is, the class would be temporary, and it would be redundant to create 2 of the same function.

Passing the list as an argument to a function is not an option, because I need it to be present during the entire existence of the class, so that any/all operations I want to do with it are available (increasing the flexibility).
Last edited on
Here is the revised Class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
template<typename type>
class pointer_class{
public:
    
    pointer_class() : dat(new type()), del(true) {}
    
    explicit pointer_class(const type& d) : dat(new type(d)), del(true) {}
    
    explicit pointer_class(type* d) : dat(d), del(false) {}
    
    ~pointer_class()
    {
        if(del)
        {
            delete dat;
        }
    }
    
    /* Returns boolean operator on the data pointed
     to by dat.*/
    bool operator==(const pointer_class<type>& d)
    {
        return (*(d.dat) == *(this->dat));
    }
    
    /* Makes pointer point to d.  Does not delete the
     data that d stores. */
    pointer_class<type>& operator=(const type& d)
    {
        *this = pointer_class(d);
        return *this;
    }
    
    pointer_class<type>& operator=(const pointer_class<type>& d)
    {
        if(this->del)
        {
            delete this->dat;
        }
        if(!d.del)
        {
            this->dat = d.dat;
        }
        if(d.del)
        {
            *(this->dat) = *(d.dat);
        }
        this->del = d.del;
        return *this;
    }
    
    /* Allows modification of dat, as well as access to member functions, 
     * but not the pointer. */
    type& gdata()
    {
        return *(this->dat);
    }
    
    type gdata_const() const
    {
        return *(this->dat);
    }
    
private:
    type *dat;
    bool del;
    
};
Alright.... so... I made a few changes to the class. I have difficulty with pointers, due to their... odd properties. I suppose that's the reason I'm writing this class.

anyway, I made some changes:
- Setting the class equal to an object allocates new space and copies the object.

- Setting the class equal to the address, or pointer will make the class not delete the pointer (It's one way or the other... correct me if there's a way to avoid this).

- Added some correcting to the operator=()

I'm getting a runtime error, and I can't fathom what is happening!!

Here is the new class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
template<typename type>
class pointer_class{
public:
    
    pointer_class() : dat(new type()), del(true) {}
    
    explicit pointer_class(const type& d) : dat(new type(d)), del(true) {}
    
    explicit pointer_class(type* d) : dat(d), del(false) {}
    
    ~pointer_class()
    {
        if(del)
        {
            delete this->dat;
            this->dat = NULL;
        }
    }
    
    /* Returns boolean operator on the data pointed
     to by dat.*/
    bool operator==(const pointer_class<type>& d)
    {
        if(this->dat == NULL)
        {
            return (this->dat == d.dat);
        }
        return (*(d.dat) == *(this->dat));
    }
    
    /* Makes pointer point to d.  Does not delete the
     data that d stores. */
    pointer_class<type>& operator=(const type& d)
    {
        *this = pointer_class(d);
        return *this;
    }
    
    pointer_class<type>& operator=(const pointer_class<type>& d)
    {
        if(this->del)
        {
            delete this->dat;
            this->dat = NULL;
        }
        if(!d.del)
        {
            this->dat = d.dat;
        }
        if(d.del)
        {
            if(this->dat == NULL)
            {
                this->dat = new type();
            }
            if((d.dat != NULL) && (d.dat != this->dat))
            {
                *(this->dat) = *(d.dat);
            }
        }
        this->del = d.del;
        return *this;
    }
    
    /* Allows modification of dat, as well as access to member functions, 
     * but not the pointer. */
    type& gdata()
    {
        return *(this->dat);
    }
    
    type gdata_const() const
    {
        return *(this->dat);
    }
    
private:
    type *dat;
    bool del;
    
};


Runtime error happens here (in another class):

1
2
3
4
5
6
7
8
9
10
11
12
13
for(vector<string>::const_iterator it = this->paths.gdata_const().begin(); it != this->paths.gdata_const().end(); ++it)
    {
        if(*it == s)
        {
            cout<< *it<< " IS SELECTED"<< endl;
            return true;
        }
    }
    cout<< s<< " is not selected; "<< endl;
    for(vector<string>::const_iterator it = this->paths.gdata_const().begin(); it != this->paths.gdata_const().end(); ++it)
    {
        cout<< "\""<< *it<< "\""<< endl; //Runtime error; it spits out a bunch of (seemingly) random stuff
    }


Thanks for the help.
Last edited on
So, I find I can't use vector<string>::iterator or vector<string>::const_iterator with the class.... any suggestions??
closed account (o1vk4iN6)
You're creating a copy every iteration of the loop when you call gdata_const() and the iterator is that of a temporary copy that was destroyed:
type gdata_const() const;
oooh... Hmm...

Thanks.

I'm trying to emplement a different approach now:

type* gdata() const Currently testing...
Last edited on
Topic archived. No new replies allowed.