The problem is your class contains a pointer.
It is very rare for real code to need to contain OWNED pointers. They are usually wrapped in some utility class (like a smart pointer or a container) or more usually they are simple objects.
Your code should look like this:
class Sample
{
public:
    int val;    // No need to make it a pointer
    Sample(int i)
       : val(i)
    {}
    void PrintVal()
    {  cout << "The value is " << val;
    }
};
If you need a dynamically allocated object then it should be in a smart pointer (assuming you want a shared resource then it looks like this.
class Sample
{
public:
    std::shared_ptr<int>  ptr;
    Sample(int i)
        :ptr(new int(i))
    {}
    void PrintVal()
    {
        cout << "The value is " << *ptr;
    }
};
Assuming you are writing your own pointer wrapper (bad idea), but lets assume it is for practice with pointers. Then you need to obey the rule of three. This is because the compiler generated versions of copy constructor and assignment operator will not do the correct thing for OWNED RAW pointers. an OWNED RAW pointer is an a pointer that you own and are thus responcable for deleting.
There are two solutions to this problem. Make the copy constuctor and assignment operators private. This will stop your code working, so I assume that is not what you want. So we need to make them work. Since the shared case is covered above by std::shared_ptr<> here we will cover the non shared case of making copies.
class Sample
{
public:
    int *ptr;   // OWNED RAW POINTER
    Sample(int i)
       : ptr(new int(i))
    {}
    ~Sample()
    {
        delete ptr;
    }
    Simple(Simple const& copy)
        : ptr(new int (*(copy.ptr)))
    {}
    Simple& operator=(Simple rhs)    // Assignment uses the copy and swap idium.
    {                                // Notice the parameter is passed by value to get
        std::swap(ptr, rhs.ptr);     // an implicit copy using the copy constructor.
    }                                // Then we simply swap the pointers. The copy will be
                                     // destroyed with the old pointer.
    void PrintVal()
    {
        cout << "The value is " << *ptr;
    }
};