I am lost in this declaration - int (*(*foo)(double))[3];
My understanding is that this is an array with size 3 which element is a function pointer taking double and returning pointer to int. However, the correct explanation seems to be "pointer to function taking double and returning pointer to array of 3 int". The returning pointer to array of 3 int confuses me a lot as int and [3] far apart.
Why is that? What is the syntax or rule to declare variables like this complex?
You just read from the inside out remembering that postfix array ([]) and function "call" (()) bind tighter than prefix pointer (*):
(*foo) // foo is a pointer...
(*foo)(double) // to a function taking a double...
(*(*foo)(double)) // returning a pointer...
(*(*foo)(double))[3] // to an array of 3...
int (*(*foo)(double))[3]; // ints
(To work out where to start you might want to work from the outside in, but you need to read back from the inside out to read the declaration in the conventional order.)
You can use "clockwise spiral rule"
+----------------------------------+
| +---------------------------+ |
| | +--------------------+ | |
| | | +----+ | | |
| | | |+--+| | | |
| | | |^ || | | |
int ( * ( *foo)( double ) [3 ];
| ^ ^ ^ ^ || | | |
| | | | +---+| | | |
| | | +------+ | | |
| | +------------------------+ | |
| +------------------------------+ |
+-------------------------------------+
Thus, Identifier foo
is a pointer
to function taking double as argument returning
pointer to
array 3
of int
Related
what's the difference between these two lines of code in c++?
size_t (*B)[N] = new size_t[N][N]; and
size_t *B[N] = new size_t[N][N];
first one compiles correctly but with second line, g++ gives this error
matrixim.cpp:43:20: error: array must be initialized with a brace-enclosed initializer
43 | size_t *B[N] = new size_t[N][N];
size_t *B[N]
Here, B is an array of N pointers to size_t
size_t (*B)[N]
Here, B is a pointer to an array of N size_ts
Both of these constructs could be used to create something approximating a 2-dimensional array, but their layout in memory is very different.
size_t *B[N] would look something like this:
B +-------------+-------------+-----+-------------+
+--------+ | B[0][0] | B[0][1] | ... | B[0][N-1] |
| B[0] +--->+-------------+-------------+-----+-------------+
+--------+
| B[1] +--->+-------------+-------------+-----+-------------+
+--------+ | B[1][0] | B[1][1] | ... | B[1][N-1] |
| | +-------------+-------------+-----+-------------+
| ... |
| |
+--------+
| B[N-1] +--->+-------------+-------------+-----+-------------+
+--------+ | B[N-1][0] | B[N-1][1] | ... | B[N-1][N-1] |
+-------------+-------------+-----+-------------+
B is an array of N pointers to size_t, each of which points to the first element of an array of N size_t.
size_t (*B)[N] would look something like this:
B +---------------------------------------------------+
+----+ | B[0] |
| +--->+ +-------------+-------------+-----+-------------+ |
+----+ | | B[0][0] | B[0][1] | ... | B[0][N-1] | |
| +-------------+-------------+-----+-------------+ |
+---------------------------------------------------+
| B[1] |
| +-------------+-------------+-----+-------------+ |
| | B[1][0] | B[1][1] | ... | B[1][N-1] | |
| +-------------+-------------+-----+-------------+ |
+---------------------------------------------------+
| |
| ... |
| |
+---------------------------------------------------+
| B[N-1] |
| +-------------+-------------+-----+-------------+ |
| | B[N-1][0] | B[N-1][1] | ... | B[N-1][N-1] | |
| +-------------+-------------+-----+-------------+ |
+---------------------------------------------------+
Here, B is a pointer to the first element of an array of N arrays of N size_t.
I understand as Set size of vector of vectors at run time
describes, one can declare vector of vector as
vector<vector<int> > ref;
then resize the first level by
ref.resize(i);
and push element at the 2nd level:
ref[i].push_back(23);
But how are vector of vector aligned in memory?
For simple vector, it's a container and align its element continuously, like an array; but in the case of vector of vector, I couldn't see the picture.
As the size of each inner vector (the vector in vector of vector) size might change, does the outer vector of vector (the vector in vector of vector) align inner vectors continously? Does the outer vector researve memeory space for each inner vector? what if one vector overshoot?
The size of the vector<int> struct that is stored in ref is constant. Common implementations has this as three pointers, or around 12 bytes on 32-bit architectures, or 24 bytes on shiny new 64-bit architectures.
So ref manages roughly ref.capacity() * 12 bytes of continuous storage.
Each element/vector<int> in ref manages its own integers independent of the elements ref manages. In the artistic rendering below ref.size() == ref.capacity() for the sake of simplicity.
So your
ref.resize(i);
only affects the top row. Your
ref[i].push_back(23);
only affects the i-th column.
vector<vector <int>> m;
The inner vector or rows are implemented as independent
objects on the free store.
Elements in each row are compactly stored, capable of performing dynamic allocation through push_back and resizing.
It is not necessary for each inner vector in the vector< vector<int> > to have the same size. So, the inner-vectors (not their elements) are not stored contiguously. That means, the first element of m[i] is not stored in the address immediately next to the last element of m[i-1].
does the outer vector of vector (the vector in vector of vector) align inner vectors continously?
No. See point#2
Does the outer vector researve memeory space for each inner vector?
No. See point#1. you need to resize or do push_back into inner vector.
how are vector of vector aligned in memory?
vector<T> vec;
consumes this much memory
sizeof(vector<T>) + (vec.size() ∗ sizeof(T))
where,
sizeof(vector<T>) = 12 bytes
and T is vector<int> for a vector of vector.
So, the memory consumed for a 3-by-4 vector<vector<int>> would be.
= sizeof(vector<vector<int>>) + (vec.size() * sizeof(vector<int>))
= 12 + 3 * 12
= 48
what if one vector overshoot?
vector.resize function corrupting memory when size is too large
A vector<vector<int>> could look like this in memory:
+-+-+-+
|b|e|c| vector<vector<int>
+-+-+-+
| | |
| | +-------------------+
| | |
| +---------------+ |
| | |
V V V
+-+-+-+-+-+-+-+-+-+
|b|e|c|b|e|c|b|e|c| 3x vector<int>
+-+-+-+-+-+-+-+-+-+
| | | | | | | | |
| | | | | | | | +-------------+
| | | | | | | | |
| | | | | | | +-------+ |
| | | | | | | | |
| | | | | | V V V
| | | | | |+-+-+-+-+-+
| | | | | ||i|i|i|i|i| 5x int
| | | | | |+-+-+-+-+-+
| | | | | |
| | | | +-+---+
| | | | |
| | | V V
| | |+-+-+-+-+
| | ||i|i|i|i| 4x int
| | |+-+-+-+-+
| | |
| +-+-----------+
| |
V V
+-+-+-+-+-+-+-+-+
|i|i|i|i|i|i|i|i| 8x int
+-+-+-+-+-+-+-+-+
Here b denotes the begin() poiner, e denotes the end() pointer and c denotes the capacity() pointer.
You see, that the rows are not contiguous in memory as you would expect from a matrix structure. Every vector (inner and outer vectors) takes care of it's own memory allocations. The outer vector does not care about what it's elements are doing.
All, my professor gave us the following loop for use in this weeks assignment:
char *ptr1, *ptr2;
char c;
ptr1 = &arr[0];
ptr2 = &arr[idx-1];
while(ptr1 < ptr2){
c = *ptr1;
*ptr1 = *ptr2;
*ptr2 = c;
ptr1++;
ptr2--;
}
Is this about the position of ptr1 vs. ptr2? The program reverses a c_str and works just fine, I just don't understand why.
Do you have a problem understanding any of the individual statements? If not, then seeing how it works is just a question of going through the steps.
The first three statements of the loop swap the character pointed by ptr1 and the one pointed by ptr2. Initially, ptr1 and ptr2 point to the first and last characters of the string. The second pass, they are pointing to the second and the second-last characters of the string, etc.
Initially:
+-----+-----+-----+-----+-----+-----+ +-----+
arr --> | a | b | c | d | e | NUL | c | ? |
+-----+-----+-----+-----+-----+-----+ +-----+
^ ^
| |
ptr1 ptr2
After c = *ptr1;:
+-----+-----+-----+-----+-----+-----+ +-----+
arr --> | a | b | c | d | e | NUL | c | a |
+-----+-----+-----+-----+-----+-----+ +-----+
^ ^
| |
ptr1 ptr2
After *ptr1 = *ptr2;:
+-----+-----+-----+-----+-----+-----+ +-----+
arr --> | e | b | c | d | e | NUL | c | a |
+-----+-----+-----+-----+-----+-----+ +-----+
^ ^
| |
ptr1 ptr2
After *ptr2 = c;:
+-----+-----+-----+-----+-----+-----+ +-----+
arr --> | e | b | c | d | a | NUL | c | a |
+-----+-----+-----+-----+-----+-----+ +-----+
^ ^
| |
ptr1 ptr2
After ptr1++; ptr2--;:
+-----+-----+-----+-----+-----+-----+ +-----+
arr --> | e | b | c | d | a | NUL | c | a |
+-----+-----+-----+-----+-----+-----+ +-----+
^ ^
| |
ptr1 ptr2
After another pass:
+-----+-----+-----+-----+-----+-----+ +-----+
arr --> | e | d | c | b | a | NUL | c | b |
+-----+-----+-----+-----+-----+-----+ +-----+
^ ^
| |
ptr1 ptr2
Loop ends.
Let's say you have a string.
+---+---+---+---+---+---+---+---+---+---+---+
| t | h | i | s | | i | s | | f | o | o |
+---+---+---+---+---+---+---+---+---+---+---+
Now let's say ptr1 and ptr2 point to:
ptr1 ptr2
| |
v v
+---+---+---+---+---+---+---+---+---+---+---+
| t | h | i | s | | i | s | | f | o | o |
+---+---+---+---+---+---+---+---+---+---+---+
at the start of the while loop. You can now follow the lines in the
while loop one step at a time to understand why the code reverses the
string.
Assume I have a pile of rectangles, some of which intersect, some isolate. E. g.
+--------------- + +-------- +
| | | |
| | | |
| A | | C |
| +---------------- + | |
| | | | +---------+-------- +
| | | | | |
+---------|----- + B | | D |
| | | |
| | +------------------ +
+---------------- +
+------------------ + +-------- +
| | | |
| E | | X |
+-------------------+ | |
| | +-------- +
| | +------------ +
| | | |
| F | | |
| | | Y |
| | | |
+-------------------+ +------------ +
Rect A, B intersect with each other, C, D have one same point, E, F have two same points, X, Y are isolated.
I have two questions:
How to partion these rectangles into rectangles which cover A, B, C, D, E, F, X, Y exactly also have minimum count like this:
+---------+----- + +-------- +
| | | | |
| | | | |
| | | | |
| | +--------- + | |
| | | | +---------+-------- +
| | | | | |
+---------+ | | | |
| | | | |
| | | +-------------------+
+------+----------+
+------------------ + +-------- +
| | | |
| | | |
| | | |
| | +---------+
| | +------------ +
| | | |
| | | |
| | | |
| | | |
+-------------------+ +-------------+
How to cover intersected rectangles with big ones? Like this:
+---------------------------+ +-------------------+
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | +-------------------+
+---------------------------+
+-------------------+ +---------+
| | | |
| | | |
| | | |
| | +---------+
| | +------------ +
| | | |
| | | |
| | | |
| | | |
+-------------------+ +-------------+
For Q1, I've no idea at all....
For Q2, I wrote some code in C++ but have poor efficiency. I believe there're better methods/algorithm.
bool intersectRect(const Rect& rect1, const Rect& rect2) {
/* if rect1 and rect2 intersect return true
else return false
*/
}
Rect mergeIntersectRects(const set<Rect>& rects) {
// suppose rects are all intersected. This function only return a smallest Rect that cover all rects.
}
set<Rect> mergeRectToRects(const set<Rect>& rectset, const Rect& rect) {
set<Rect> _intersect_rects;
set<Rect> _unintersect_rects;
for(set<Rect>::const_iterator it = rectset.begin();
it != rectset.end();
++it) {
if(intersectRect(*it, rect))
_intersect_rects.insert(*it);
else
_unintersect_rects.insert(*it);
}
if(!_intersect_rects.empty()) {
_intersect_rects.insert(rect);
return mergeRectToRects(_unintersect_rects,
mergeIntersectRects(_intersect_rects));
}
else {
_unintersect_rects.insert(rect);
return _unintersect_rects;
}
}
First, I'm assuming that your rectangles are all axis-aligned.
For Q1, one option would be to sweep the plane while maintaining a list of line segments along the sweep line that lie in the interior of the rectangles. As you discover each rectangle vertex during the sweep you can check to see if it modifies the current interior segments and if so, start or end a rectangle as necessary.
For example, let's say your sweep line moves left to right:
Current
Interior
|
+-|------------- + +-------- + *
| | | | | |
| | | | | |
| | A | | C | |
| | +---------------- + | | |
| | | | | +---------+-------- + |
| | | | | | | |
+-|-------|----- + B | | D | *
| | | | |
| | | +------------------ +
| +---------------- +
|
+-|---------------- + +-------- + *
| | | | | |
| | E | | X | |
| |-----------------+ | | |
| | | +-------- + |
| | | +------------ + |
| | | | | |
| | F | | | |
| | | | Y | |
| | | | | |
+-|-----------------+ +------------ + *
|
When the sweep line is in the position shown above, there are two interior segments. Namely, that inside A and that inside (E U F). When the sweep line reaches the leftmost edge of B, we output a rectangle for the portion of A lying to the left. We then replace the interior of A in the segment list with the interior of (A U B).
Current
Interior
|
+---------+-|--- + +-------- + *
| | | | | | |
| | | | | | |
| | | | | C | |
| | |-------------- + | | |
| | | | | +---------+-------- + |
| | | | | | | |
+---------+ |--- + B | | D | |
| | | | | |
| | | +------------------ + |
+-|-------------- + *
|
+-----------|------ + +-------- + *
| | | | | |
| | | | X | |
| |-------+ | | |
| | | +-------- + |
| | | +------------ + |
| | | | | |
| | | | | |
| | | | Y | |
| | | | | |
+-----------|-------+ +------------ + *
|
For Q2, the answer could be computed during the same sweep by keeping track of the x-coordinate at which a segment was first added to the list (e.g. "left side of A") as well as the min and max y-coordinates that it spans during its lifetime (e.g. bottom of B to top of A). When the segment is finally removed from the list (e.g. "right side of B"), then output a rectangle using these four coordinates.
Sorting the rectangle vertices lexicographically in a preprocessing step would be O(n * log n). Processing them would be O(log n) since you can do a binary search on the known interior ranges. The total runtime should be O(n * log n).
Q1: this is called partition of rectilinear polygon. Answer from Rob's comment has very good description. I found paper mentioned in the answer useful.
Q2: I suppose that you don't want two covers of non-intersecting regions to intersect. Like cover for 3 rectangle, 2 rectangle producing L and rectangle intersection cover of L but not any L rectangle.
If it is like that, than it is possible to incrementally create covers. Here is a simple algorithm for it.
covers = {A}
for each rectangle R
while there is a cover that intersects R, say C
remove C from covers and set R = cover of R and C
add R to covers
This code is not efficient in standard form. With good structure for covers structure, it can be efficient.
Here's the algorithm: http://goo.gl/aWDJo
You can read about finding the convex hull algorithms: http://ralph.cs.cf.ac.uk/papers/Geometry/boxing.pdf
I'd use the method suggested by #Damon but speed up neighbouring rectangle search with some spatial indexing structure, for example a quadtree or a grid. You'd need two of them, first built over the set of input rectangles, to search for intersecting rectangles to split, and second built over the set of split rectangles obtained in first step, to search adjacent rectangles to merge. That should speed things up considerably compared to the naive approach.
class CSensor
{
public:
CSensor(int nVal1,char* pVal2,unsigned int nVal3);
CSensor(const CSensor& refMessage);
const CSensor& operator=(const CSensor& refMessage);
~CSensor(void);
private:
int m_nVal1;
char* m_pVal2;
unsigned int m_nVal3;
};
// vector erase
std::vector<CSensor> SensorList;
CSensor obj1(1,"Test1",10);
SensorList.push_back(obj1);
CSensor obj2(2,"Test2",11);
SensorList.push_back(obj2);
CSensor obj3(3,"Test3",12);
SensorList.push_back(obj3);
SensorList.erase (SensorList.begin()+1);
// map erase
std::map<int ,CSensor> ListSensor;
CSensor obj11(1,"Test1",10);
CSensor obj12(2,"Test2",11);
CSensor obj13(3,"Test3",12);
ListSensor.insert(std::pair<int,CSensor>(1,obj11));
ListSensor.insert(std::pair<int,CSensor>(2,obj12));
ListSensor.insert(std::pair<int,CSensor>(3,obj13));
ListSensor.erase(2);
I debugged both the case.
In both the cases i am deleting the second element.In case of vector
it is copying 3 element to 2nd poition and than it it deleting the 3 rd location.
So when u say
List.erase (List.begin()+1);
it is calling assignment operator(CSensor=) and then calling destructor.
In case of map when i do
ListSensor.erase(2);
it only calls the destructor.
I have gone through STL vector vs map erase.
It talks Iterator,couldn't explain the behavior.
My question is why erase behaves differently for these two STL container??
This is not a behaviour of .erase per se, but a consequence of how each respective container works.
Deleting from a vector
When you delete from a vector (List is a really poor name for a vector, btw), its contents must be shuffled along to fill the gap because the elements of a vector are always stored contiguously in memory.
This is generally done by copying (or moving) elements then chopping off the remainder:
Vector elements in memory:
+---+---+---+---+---+---+---+---+---+
| a | b | c | d | e | f | g | h | i |
+---+---+---+---+---+---+---+---+---+
Erase 'e':
+---+---+---+---+---+---+---+---+---+
| a | b | c | d | | f | g | h | i |
+---+---+---+---+---+---+---+---+---+
Fill the gap by copying/moving across:
<--
+---+---+---+---+---+---+---+---+---+
| a | b | c | d | f | f | g | h | i |
+---+---+---+---+---+---+---+---+---+
<--
+---+---+---+---+---+---+---+---+---+
| a | b | c | d | f | g | g | h | i |
+---+---+---+---+---+---+---+---+---+
<--
+---+---+---+---+---+---+---+---+---+
| a | b | c | d | f | g | h | h | i |
+---+---+---+---+---+---+---+---+---+
<--
+---+---+---+---+---+---+---+---+---+
| a | b | c | d | f | g | h | i | i |
+---+---+---+---+---+---+---+---+---+
Resize the container:
+---+---+---+---+---+---+---+---+
| a | b | c | d | f | g | h | i |
+---+---+---+---+---+---+---+---+
Deleting from a map
This is not the case for a map, whose contents are not necessarily stored contiguously in memory (in fact, the complexity requirements mean it's almost always a tree structure filled with pointers to discontiguous data).
This is one reason to have different containers!
The vector has to copy the elements following the eased element to cover the "hole" that it left. Otherwise the elements wouldn't be contiguous anymore.
The map holds its elements in a tree structure and just has to adjust some pointers to rebalance the tree.
To the vector's defense: Copying a couple of elements might be cheaper than allocating tree nodes separately and keeping the tree balanced. There are always tradeoffs!