Which is better, to define the variable inside the loop or outside, with huge loop times [closed] - c++

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 1 year ago.
Improve this question
I need to use an array in a loop, and the loop time is very huge.
Case 1: define the array outside the for-loop and pass it to fun2
void fun1(){
int temp[16];
for(int i = 0;i <times; i++)
{
fun2(temp);
}
}
void fun2(int[]& temp){
/** do something with temp*/
}
Case 2: define the array in fun2:
void fun1() {
for (int i = 0; i < times; i++)
{
fun2();
}
}
void fun2() {
int temp[16];
/** do something with temp */
}
fun1 will be called very often. In this situation, which is better?
Does Case 2 have some influence on performance?

If you look for an answer to the general case, the answer is, "it depends." If you want an answer to your specific example, the answer is that the second version will be more efficient.
Ask yourself:
Is there a cost to construction / destruction / reuse?
In your example, there is none (except adjusting the stack pointer, which is extremely cheap). But if it was an array of objects, or if you had to initialize the array to a specific value, that changes.
How does the cost of parameterization factor in?
This is very minor but in your first case, you pass a pointer to the function. If the function is not inlined, this means that the array can only be accessed through that pointer. This takes up one register which could be used otherwise. In the second example, the array can be accessed through the stack pointer, which is basically free.
It also affects alias and escape analysis negatively which can lead to less efficient code. Basically, the compiler has to write values to memory instead of keeping them in registers if it cannot prove that a following memory read may not refer to the same value.
Which version is more robust?
The second version ensures that the array is always properly sized. On the other hand, if you pass an object whose constructor may throw an exception, constructing outside the function may allow you to throw the exception at a more convenient location. This could be significant for exception safety guarantees.
Is there a benefit in deallocating early?
Yes, allocation and deallocation are costly, but early destruction may allow some reuse. I've had cases where deallocating objects early allowed reuse of the memory in other parts of the code which improved use of the CPU cache.

depends on what you want to achieve..in this case, i'm assuming you are looking for performance which case 2 would be the better option as the function would create the variable on the fly instead of trying to get the variable globally then its value.

Related

Why use std::vector instead of realloc? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
Here, in this question, it's stated that there is no realloc-like operator or function in c++. If you wish to resize an array, just just std::vector instead. I've even seen Stroustrup saying the same thing here.
I believe it's not hard to implement one. There should be a reason for not implementing one. The answers only say to use std::vector but not why it's not implemented.
What is the reason for not implementing realloc-like operator or function and preferring to use std::vector instead?
What is the reason for not implementing realloc-like operator or function and preferring to use std::vector instead?
Save time. Don't chase bugs in your own code for a problem that has long been solved. Idiomatic C++ and readability. Get answers to your questions easily and quickly. Customize the realloc part by an allocator.
I believe it's not hard to implement one
That heavily depends on what you need from the template you intend to write. For a general-purpose std::vector-like one, have a look at the source code (libcxx's 3400 line vector header is here). I bet you will revise you initial assumption on the low complexity of such construct.
There's several advantages.
Vector keeps track of its size and capacity, which means you don't have to do this yourself.
Because the current size is part of the vector object itself, you can pass a vector (by reference or by value) without needing an additional size parameter. This is especially useful when returning a vector as the caller doesn't need to receive the size through some side-channel.
When reallocating, vector will add more capacity than is needed to add just the element(s) requested to be added. This sounds wasteful but saves time as fewer reallocations are needed.
Vector manages its own memory; using vector lets you focus on the more interesting parts of your program instead of the details of managing memory, which are relatively uninteresting and tricky to get exactly right.
Vector supports many operations that arrays don't natively support, such as removing elements from the middle and making copies of an entire vector.
realloc's expectation that there might be sufficient free space after the current allocation just does not fit well with modern allocators and modern programs.
(There's many more allocation going on, many allocation sizes go to a dedicated pool for that size, and the heap is shared between all the threads in a program.)
In most cases, realloc will have to move content to a completely new allocation, just like vector does. But unlike vector<T>, realloc does not know how to move elements of type T, it only knows how to copy plain data.
Well, as the other answers have explained nicely about the reason for using vectors, I will simply elaborate on why realloc was not implemented. For this, you need to take a look at what realloc actually does. It increases the size of the memory by intelligently using malloc() and free(). You need to understand, that though it seems to simply increase the size, it does not actually increase the size, but instead allocates another block of memory with the required size (That explains the name realloc).
Take a look at the following lines:
int* iarr = (int*)malloc(sizeof(iarr)*5);
iarr = (int*)realloc(6,sizeof(iarr)); //this is completely discouraged
//what you're supposed to do here is:
int* iarr2 = (int*)realloc(iarr,1 + sizeof(iarr)); //copies the old data to new block implicitly
//this not only saves the previous state, but also allows you to check if realloc succeeded
In C++, this can be (if it is must) achieved, by writing:
int* iarr = new int[5];
int* iarr2 = new int[6];
for(int i = 0; i < 5; i++) {
iarr2[i] = iarr[i];
}
delete[] iarr;
The only use of realloc was to increase the memory capacity; as C arrays did not do that automatically they had to provide a mechanism to do so; which has been implicitly implemented in most of the containers, making the reason for having a realloc in the first place, moot.

What is the best way to initialize an iterator? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this question
When I started studying C/C++, in my first lessons I learned that we must always declare the variables before using it in our code. So:
int iterator = 0; // with optional initialization of value accordingly with its use.
for (iterator = 0 ; ; ) // your loop
In this case, we can reuse the same variable iterator for as many loops as we want, without need to declare a variable for each loop.
However, I discovered recently that we can also declare and initialize a variable inside the for loop:
for (int iterator = 0 ; ; ) // your loop
In this case, the scope of iterator is only inside de for loop. As it is used as an iterator, and have no other use outside the loop, once it ends, the variable is lost.
Which leads me to question: what is the best way to initialize an iterator?¹ Is there a ''best practice'' towards this feature?
¹ = (in terms of most efficient / or resource (RAM) usage / or fastest computation)
The word iterator has a specific meaning in C++, and this is not what an iterator is. This is usually called a counter or a loop variable.
(in terms of most efficient / or resource (RAM) usage / or fastest computation)
In the described case, there is practically no difference whatsoever in these terms.
It is usually good design for the scope of a variable to be as small as possible. In this case, that is achieved by declaring the counter within init-statement of the loop. Following this rule-of-thumb often makes it easier for the compiler to minimise memory use, and more importantly, reduces cognitive load of the programmer who needs to grok the algorithm.
There are some algorithms where the final value of the counter is needed after the loop. Such algorithm can be accommodated by hoisting the variable scope out of the scope of the loop.
¹ = (in terms of most efficient / or resource (RAM) usage / or fastest computation)
Generally, as far as these metrics are concerned, they are equivalent; any modern compiler will statically allocate the stack frame at the function entry and reuse the space across scopes. You can easily see here that the code generated for the two functions is exactly the same.
Moreover, integer variables don't require any particular initialization1, so it's not like creating new ones at each loop has any cost in runtime.
So, as a rule of thumb you should apply the usual rule of keeping each variable to the narrowest required scope, to reduce cognitive load when reading (you know immediately that such variable has only meaning inside that loop, no need to worry about its value being used later, no need to search for it around when you look for its definition) and reduce the risk of bugs (such as not re-initializing it later and reusing its stale value).
Unlike more complex types, which may invoke costly constructors for each instance; more in general, types used for iterators (be them pointers or STL containers iterator) are cheap to construct.

Which data structure can i use if i want to reduce its memory by half during the execution [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I want to half the number of elements that the data-structure contains. And I have to do that multiple times.
The problem is similar to this:
I have 'n' sorted integers and I have to add consecutive two numbers. Thus the number of the number of integers I am left with is n/2.And I have to loop this till I get a single number. ( I simplified the problem, I have to do other operations side by side)
I thought trying an array of size n, then thought I will create an array of size n/2 and will fill this new array, and finally will free the original array(was created using a pointer). Note that I also have to store the data I evaluated each time through the loop.
If I am not able to explain, please refer to this problem
MIXTURE
Use a pointer to memory allocated with malloc (or calloc, or similar), then resize it with realloc:
int main()
{
int* myArray = malloc(50 * sizeof(int)); // gets you 50 integers
// perform operations on myArray, accessing it like myArray[3]
int* r = realloc(myArray, 25 * sizeof(int));
if (r) {
myArray = r;
}
// perform some more operations.
free(myArray); // free the memory once you are done with it
}
realloc returns a new pointer that points to memory of the same content as the pointer you passed before. Assign the result back to myArray like this to get the desired behavior, and when you don't need the array anymore, call free on it just like you would do normally if you haven't reallocated it.
Which data structure can i use if i want to reduce its memory by half during the execution
I want to half the number of elements that the data-structure contains. And I have to do that multiple times.
You can use any dynamically sized data structure, which is pretty much all data structures except the statically sized array.
Although, note that reducing the size of memory allocated for std::vector (upon calling shrink_to_fit) is technically not guaranteed to happen. Example using vector:
vec.resize(vec.size() / 2);
vec.shrink_to_fit();

Is having a loop in C++ constructor a good Idea? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
I was writing code for my homework. So as I finished one of my classes I ran into a question. Is having a loop to assign values to array a good idea?
This is my class. I was thinking of making either loop in the constructor or create a function which would assign values later, by calling it manually.
Are these choices different? if yes, Which choice is better and why?
class Mule
{
private:
int numofMules;
int MapSize;
MuleNode* field;
MuleNode* mules;
public:
void random_positions();
void motion();
void print_field();
Mule(int nofMules, int mSize)
{
numofMules = nofMules;
MapSize = mSize;
mules = new MuleNode[numofMules];
field = new MuleNode[MapSize*MapSize];
for(i = 0; i < numofMules; i++)
{
mules[i].ID = i+1;
}
random_positions();
}
}
Edited the code because of the problem with allocation of one dimensional array at compilation time and recreated 2 dimensional array in 1 dimensional using formulas.
+---------------+-----------+-----------+
| i = j * w + i | x = i % w | y = i / w | w - width of the 2 dimentional array
+---------------+-----------+-----------+
Conclusion: As the question was marked as opinion-based, I guess it means that there is no big difference in using loop in the constructor or creating a function which would assign values later.
If there are any facts or opinions about this question worth sharing, please comment or write your answer.
There's not necessarily anything terrible about having a loop in a ctor.
At the same time, it's worth considering whether those items you're initializing couldn't/shouldn't be objects that know how to initialize themselves instead of creating uninitialized instances, then writing values into them.
As you've written it, the code doesn't really seem to make much sense though. The class name is Mule, but based on the ctor, it's really more like a collection of Mules. A Mule should be exactly that: one mule. A collection of N mules should be something like a std::vector<Mule>. A Mule that's really a collection of Mules is a poor idea.
You should also at least consider using std::vector instead of an array (assuming that you end up with a collection of items in the class at all, of course).
In general, not a good idea, but some constructors require a loop (example, initializing an array in heap, which is initialized in the constructor). But not all constructors are called so often (singletons, for example, called only once per process).
In the end, it depends on the class and program/object design.
Your particular class appears like it will be created only once per process. So my take is that it is OK. If that is not the case, then we have to evaluate it on a case-by-case basis.

Why are memory addresses in pointers important [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I personally believe I have a firm grasp of pointers, but let's say
int* pMyPointer;
int number = 1000;
pMyPointer = &number;
cout << pMyPointer << endl;
pMyPointer might return a memory address of 0037FBB0, but why does that matter? How can this be useful while programming?
Object identity.
If you have two pointers or references, how can you tell if using one could affect the other? Simply printing the current value of all the data members won't tell you if they are the same object or clones/copies.
So when you're debugging, you become very interested in whether the addresses stored in different pointers are the same, which requires you to inspect those address values.
This is a very important information in static memory management.
In userspace application development, this information might be irrelevant to the most developers, but they are very important for the low-level developer. Remember, programming languages with static memory manager will always be lower level languages.
This also the main point in how pointers work. They store memory addresses to where they point.
You can also create a pointer like this: int *mptr = (int*)0x13371234;. This creates a pointer which points to the int at 0x13371234.
It also gives you information about where your stuff in stored, and this can also be used to determine the location of the stack, if for any reason inline assembly is not allowed. If you use malloc, then it is generally not a must-need information.
A typical use is to create linked data structures like lists and trees.
For example, in a binary tree each node contains a pointer to its two children.
As far as the pointer goes, the actual value only rarely means much in itself. It's usually used as a "magic cookie" -- an essentially "magic" value gives you access to some particular variable. In a typical case you save an address into a pointer, then dereference the pointer to get to the item at that address, without ever examining (or even caring about) the value of the pointer itself.
There are a few exceptions to this general rule though. For one example, some memory allocators use the address of a block to track not only the location of the block, but also the block's size. By starting with a block aligned to a large boundary, and always splitting blocks by powers of 2, the whole address tells the location of the block, and the lower bits of the address tell the size of the block that must have been allocated to get to that address.
The latter are definitely the exceptions though. The typical case is that the value of the pointer means nothing beyond giving access to the item at that address.