Constructor and copy constructors - c++11

I have started studying C++ after some years in C# and other languages. I am facing the class arguments (constructors, inheritance, copy etc) and I was trying to write a bad sample code. Below is a sample class (.h and .cpp):
#ifndef SAMPLE_H
#define SAMPLE_H
#include <iostream>
class Sample
{
public:
Sample();
//Sample(const Sample& s);
virtual ~Sample();
int *s_array;
protected:
private:
};
void print(const Sample *s);
#endif // SAMPLE_H
Sample::Sample()
{
std::cout<<"create sample\n";
s_array=new int[10];
std::cout<<"alloc memory 10 int array\n";
for(int i=0; i<10; ++i)
{
s_array[i]=i;
}
}
Sample::~Sample()
{
//dtor
std::cout<<"Dealloc memory 10 int array\n";
delete [] s_array;
std::cout<<"destroy sample\n";
}
void print(const Sample *s)
{
std::cout<<s<<" "<<s->s_array<<'\n';
for(int i=0; i<10; ++i)
{
std::cout<<s->s_array[i]<<" ";
}
std::cout<<"\n\n";
}
Then in main
#include <iostream>
#include "Sample.h"
using namespace std;
int main()
{
cout<<endl<<"Let's try the Copy const WRONG.... "<<endl;
Sample *s1=new Sample();
print(s1);
Sample s2(*s1);
cout<<endl<<"What is s2 ??? "<<endl;
print(&s2);
delete s1;
cout<<endl<<"What is s2 NOW after s1 delete??? "<<endl;
print(&s2);
return 0;
}
I wanted to test the dangers of NOT to use the copy constr and i expected to see after the deletion of s1 a totally 'dirty' array (i.e., 10 random values or even a crash)
This is the output I gain (Win 10 pro, IDE CodeBlock, GNU Gcc compiler):
Let's try the Copy const WRONG....
create sample
alloc memory 10 int array
0x1ba110 0x1b6e48
0 1 2 3 4 5 6 7 8 9
What is s2 ???
0x6efdf0 0x1b6e48
0 1 2 3 4 5 6 7 8 9
Dealloc memory 10 int array
destroy sample
What is s2 NOW after s1 delete???
0x6efdf0 0x1b6e48
1812296 1769664 2 3 4 5 6 7 8 9
Dealloc memory 10 int array
destroy sample
Why only the first two items of s_array are 'dirty' and the remaining 8 are good? Why the deletion of object s1 does not free the whole memory pointed by s2?
Thanx in advance
Diego

Related

Segmentation Fault for Merge function of Merge Sort

My task is to implement just the merge function of merge sort algorithm.My idea is to create an auxilliary array to store the sorted values.I have mainted 2 pointers,one for left sorted array and other for right sorted array.
I am having difficulty in figuring out why am I getting segmentation fault?
void merge(int arr[], int l, int m, int r)
{
int temp[r-l+1];int count=0;
int *ptr1=(int*) malloc(sizeof(int));
int * ptr2=(int*) malloc(sizeof(int));
ptr1=&arr[l];
ptr2=&arr[m+1];
while(ptr1!=(&arr[m+1]) && ptr2!=NULL)
{
if(*ptr1>=*ptr2)
{
temp[++count]=*ptr2;
ptr2++;
}
else
{
temp[++count]=*ptr1;
ptr1++;
}
}
if(ptr1==&arr[m+1])
{
while(ptr2)
{
temp[++count]=*ptr2;
ptr2++;
}
}
if(ptr2==NULL)
{
while(ptr1!=&arr[m+1])
{
temp[++count]=*ptr1;
ptr1++;
}
}
for(int i=0;i<r-l+1;i++)
{
arr[i]=temp[i];
}
}
Input:
2
5
4 1 3 9 7
10
10 9 8 7 6 5 4 3 2 1
Expected Output:
1 3 4 7 9
1 2 3 4 5 6 7 8 9 10
My Output:Segmentation fault
First of all, these lines for malloc are not necessary
int *ptr1=(int*) malloc(sizeof(int));
int * ptr2=(int*) malloc(sizeof(int));
ptr1=&arr[l];
ptr2=&arr[m+1];
and can be changed to
int *ptr1=&arr[l];
int * ptr2=&arr[m+1];
The other problem is that the test for NULL for ptr2 does not work since the address past the last element is not NULL.

Qsort comparison

I'm converting C++ code to Go, but I have difficulties in understanding this comparison function:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <iostream>
using namespace std;
typedef struct SensorIndex
{ double value;
int index;
} SensorIndex;
int comp(const void *a, const void* b)
{ SensorIndex* x = (SensorIndex*)a;
SensorIndex* y = (SensorIndex*)b;
return abs(y->value) - abs(x->value);
}
int main(int argc , char *argv[])
{
SensorIndex *s_tmp;
s_tmp = (SensorIndex *)malloc(sizeof(SensorIndex)*200);
double q[200] = {8.48359,8.41851,-2.53585,1.69949,0.00358129,-3.19341,3.29215,2.68201,-0.443549,-0.140532,1.64661,-1.84908,0.643066,1.53472,2.63785,-0.754417,0.431077,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256,-0.123256};
for( int i=0; i < 200; ++i ) {
s_tmp[i].value = q[i];
s_tmp[i].index = i;
}
qsort(s_tmp, 200, sizeof(SensorIndex), comp);
for( int i=0; i<200; i++)
{
cout << s_tmp[i].index << " " << s_tmp[i].value << endl;
}
}
I expected that the "comp" function would allow the sorting from the highest (absolute) value to the minor, but in my environment (gcc 32 bit) the result is:
1 8.41851
0 8.48359
2 -2.53585
3 1.69949
11 -1.84908
5 -3.19341
6 3.29215
7 2.68201
10 1.64661
14 2.63785
12 0.643066
13 1.53472
4 0.00358129
9 -0.140532
8 -0.443549
15 -0.754417
16 0.431077
17 -0.123256
18 -0.123256
19 -0.123256
20 -0.123256
...
Moreover one thing that seems strange to me is that by executing the same code with online services I get different values (cpp.sh, C++98):
0 8.48359
1 8.41851
5 -3.19341
6 3.29215
2 -2.53585
7 2.68201
14 2.63785
3 1.69949
10 1.64661
11 -1.84908
13 1.53472
4 0.00358129
8 -0.443549
9 -0.140532
12 0.643066
15 -0.754417
16 0.431077
17 -0.123256
18 -0.123256
19 -0.123256
20 -0.123256
...
Any help?
This behavior is caused by using abs, a function that works with int, and passing it double arguments. The doubles are being implicitly cast to int, truncating the decimal component before comparing them. Essentially, this means you take the original number, strip off the sign, and then strip off everything to the right of the decimal and compare those values. So 8.123 and -8.9 are both converted to 8, and compare equal. Since the inputs are reversed for the subtraction, the ordering is in descending order by magnitude.
Your cpp.sh output reflects this; all the values with a magnitude between 8 and 9 appear first, then 3-4s, then 2-3s, 1-2s and less than 1 values.
If you wanted to fix this to actually sort in descending order in general, you'd need a comparison function that properly used the double-friendly fabs function, e.g.
int comp(const void *a, const void* b)
{ SensorIndex* x = (SensorIndex*)a;
SensorIndex* y = (SensorIndex*)b;
double diff = fabs(y->value) - fabs(x->value);
if (diff < 0.0) return -1;
return diff > 0;
}
Update: On further reading, it looks like std::abs from <cmath> has worked with doubles for a long time, but std::abs for doubles was only added to <cstdlib> (where the integer abs functions dwell) in C++17. And the implementers got this stuff wrong all the time, so different compilers would behave differently at random. In any event, both the answers given here are right; if you haven't included <cmath> and you're on pre-C++17 compilers, you should only have access to integer based versions of std::abs (or ::abs from math.h), which would truncate each value before the comparison. And even if you were using the correct std::abs, returning the result of double subtraction as an int would drop fractional components of the difference, making any values with a magnitude difference of less than 1.0 appear equal. Worse, depending on specific comparisons performed and their ordering (since not all values are compared to each other), the consequences of this effect could chain, as comparison ordering changes could make 1.0 appear equal to 1.6 which would in turn appear equal to 2.5, even though 1.0 would be correctly identified as less than 2.5 if they were compared to each other; in theory, as long as each number is within 1.0 of every other number, the comparisons might evaluate as if they're all equal to each other (pathological case yes, but smaller runs of such errors would definitely happen).
Point is, the only way to figure out the real intent of this code is to figure out the exact compiler version and C++ standard it was originally compiled under and test it there.
There is a bug in your comparison function. You return an int which means you lose the distinction between element values whose absolute difference is less then 1!
int comp(const void* a, const void* b)
{
SensorIndex* x = (SensorIndex*)a;
SensorIndex* y = (SensorIndex*)b;
// what about differences between 0.0 and 1.0?
return abs(y->value) - abs(x->value);
}
You can fix it like this:
int comp(const void* a, const void* b)
{ SensorIndex* x = (SensorIndex*)a;
SensorIndex* y = (SensorIndex*)b;
if(std::abs(y->value) < std::abs(x->value))
return -1;
return 1;
}
A more modern (and safer) way to do this would be to use std::vector and std::sort:
// use a vector for dynamic arrays
std::vector<SensorIndex> s_tmp;
for(int i = 0; i < 200; ++i) {
s_tmp.push_back({q[i], i});
}
// use std::sort
std::sort(std::begin(s_tmp), std::end(s_tmp), [](SensorIndex const& a, SensorIndex const& b){
return std::abs(b.value) < std::abs(a.value);
});

C++11 vector of vectors initialization

In C++11, {} is preferred over () for variable initialization. However, I noticed that {} cannot correctly initialize the vector of vectors.
Given the following code, vector<vector<int>> mat2(rows, vector<int>(cols, 2)) and vector<vector<int>> mat4{rows, vector<int>(cols, 4)} work as expected, but vector<vector<int>> mat1{rows, vector<int>{cols, 1}} and vector<vector<int>> mat3(rows, vector<int>{cols, 3}) do not. Can anybody explain why?
#include <iostream>
#include <iomanip>
#include <sstream>
#include <string>
#include <vector>
using namespace std;
string parse_matrix(const vector<vector<int>>& mat)
{
stringstream ss;
for (const auto& row : mat) {
for (const auto& num : row)
ss << std::setw(3) << num;
ss << endl;
}
return ss.str();
}
int main()
{
const int rows = 5;
const int cols = 4;
vector<vector<int>> mat1{rows, vector<int>{cols, 1}};
vector<vector<int>> mat2(rows, vector<int>(cols, 2));
vector<vector<int>> mat3(rows, vector<int>{cols, 3});
vector<vector<int>> mat4{rows, vector<int>(cols, 4)};
cout << "mat1:\n" << parse_matrix(mat1);
cout << "mat2:\n" << parse_matrix(mat2);
cout << "mat3:\n" << parse_matrix(mat3);
cout << "mat4:\n" << parse_matrix(mat4);
}
Output:
$ g++ -Wall -std=c++14 -o vector_test2 vector_test2.cc
$ ./vector_test2
mat1:
4 1
4 1
4 1
4 1
4 1
mat2:
2 2 2 2
2 2 2 2
2 2 2 2
2 2 2 2
2 2 2 2
mat3:
4 3
4 3
4 3
4 3
4 3
mat4:
4 4 4 4
4 4 4 4
4 4 4 4
4 4 4 4
4 4 4 4
For a combination of reasons, uniform initialization is kind of broken for std::vector<int> (and more generally, vector of arithmetic type). Uniform initialization uses the same syntax as list-initialization (constructing from initializer_list); when the syntax is ambiguous, the constructor taking initializer_list takes precedence.
Thus, std::vector<int> v(42); means "use std::vector(size_t) constructor to create a vector of 42 zeros"; while std::vector<int> v{42}; means "use std::vector(std::initializer_list) constructor to create a vector with a single element having value 42".
Similarly, std::vector<int> v(5, 10); uses two-parameter constructor to create a vector of 5 elements, all with value 10; while std::vector<int> v{5, 10}; uses initializer_list-taking constructor and creates a vector of two elements, values 5 and 10.

What is the size of template class in c++?

The output of the below code is 16. Why so? even without initializing with the length of array of the class the size is 16 and with initializing the length with the 2nd constructor, it is the same size i.e. 16. Any explanation?
#include <iostream>
#include <string>
using namespace std;
template <class T>
class array1{
T * arr;
int l;
public:
array1(){
arr = 0; l=0;
}
array1(int x){
l = x;
arr = new T[l];
}
~array1(){
delete[] arr;
}
void display(){
cout << "array1 is :"<<endl;
for (int i=0; i<l; i++)
cout << arr[i] << " ";
cout << endl;
}
};
int main()
{
array1<int> a1;
cout << "size of int arr is " << sizeof(a1);
return 0;
}
It is because of Data Structure alignment. In your system it is being aligned to 8 bytes word. Print the sizeof(T*) and sizeof(int) it will output 8 and 4 respectively in the constructor of array class. But when output together it takes 16 bytes.
It appears your integer and pointer types are both 8 bytes/64 bits. Also, just a heads up, sizeof is a compile-time operator, meaning that even if an object of your type allocates memory on the heap with the operator new[], sizeof will still return 16 bytes for any object of type array1.
Additionally, no matter what type you have for T, sizeof(array1<T>) will always be 16 bytes. (I am making the assumption that you are not compiling on an atypical target.)
Your class has two member variables. A pointer and an int. I suspect that both are eight bytes in size for your platform.
If so, then: 8 + 8 = 16.
(Your class has no virtual methods -- so no vtable overhead).

fread reading garbage value from stdin

The following is a code for sorting numbers based on quicksort in C. To optimize for speed, scanf() has been replaced by fread(). But on printing the sorted list, all garbage values come out. The exact problem statement is on :http://www.codechef.com/problems/TSORT
#define SIZE 32768
#include <stdio.h>
#include <stdlib.h>
int compare(const void *a, const void *b)
{
return (*(unsigned long *)a-*(unsigned long *)b);
}
int main()
{
char buffer[SIZE];
register int readBytes=0;
unsigned long bufferCounter=0, bufferedInput=0;
unsigned long * array, t, i;
scanf("%lu", &t); fflush(stdin);
array=(unsigned long *) malloc(sizeof(long)*t);
i=-1;
while(readBytes=fread(buffer, sizeof(char), SIZE, stdin)>0)
{
for(bufferCounter=0; bufferCounter<readBytes; bufferCounter++)
{
if(buffer[bufferCounter]=='\n' || buffer[bufferCounter]==' ')
{
array[++i]=bufferedInput;
bufferedInput=0;
}
else bufferedInput=bufferedInput*10+(buffer[bufferCounter]-'0');
}
}
qsort(array, t, sizeof(long), compare);
for(i=0; i<t; i++)
{
printf("%lu\n", array[i]);
}
return 0;
}
The code is compiled in Codeblocks and the input is piped from a file.
The input file is :
5
5
3
6
7
1
The output obtained is:
5050160
5056368
1465662019
1868852841
1935438711
What is the problem with my code?

Resources