So it seems it works, But what happens with the data in the while the program running?
From a technical stand point, it remains in the heap waiting to be deallocated.
This data is really free by the system?
It's free space in terms that you're allowed to use more heap, and will no longer appear in the object's memory graph, but will still be floating around in the heap somewhere until a HEAP_DEALLOCATION event.
On big programs - this clear of the heap size could come with a cost of CPU time for example?
Yes, the CPU cost does exist, but it's a very small amount compared to the time used by everything else in a typical program. While it's theoretically possible that too many allocations could cause CPU governor problems, more likely it will be something much larger that you can fix.
Side note: do not make a list from a query of records; it's already a list. Since we're on the topic of heap allocation:
account[] x = new list<account>([select id from account limit 1]);
Results in 20 HEAP_ALLOCATION events in my org, but:
account[] x = [select id from account limit 1];
Results in 15 HEAP_ALLOCATION events in my org.
Likewise, if you don't plan on using the list again, you can null it:
account[] x = [select id from account limit 1];
...
x = null;
This eliminates the associated HEAP_ALLOCATION events necessary for creating a new list and is subsequently faster.
Also, if you do need it again, you can clear the list:
account[] x = [select id from account limit 1];
...
x.clear();
This is 2 HEAP_ALLOCATION events cheaper than:
x = new account[0];