i have declared a map below using stl and inserted some values in it.
#include<bits/stdc++.h>
int main()
{
map<int,int> m;
m[1]=1;
m[2]=1;
m[3]=1;
m[4]=1;
m[5]=1;
m[6]=1;
for(auto it=m.begin();it!=m.end();)
{
cout<<it->first<<" "<<it->second<<endl;
it=it++;
}
return 0;
}
When i executed the above written code it ended up in an infinite loop. Can someone tell me why it does so?
I am incrementing the value of iterator it and then it gets stored in it which should get incremented next time the loop is executed and eventually it should terminate normally.Am i wrong?
The bad line is it = it++;. It is undefined behavior! Because it is not defined, when it is increased, in your case it is increased before the assingment to itsself again, that the value of it before it is increased is assigned to it again and so it keeps at the first position. The correct line would be it = ++it; or only ++it;/it++;, because it changes itsself.
Edit
That is only undefined with the builtin types, but in here that is defined by the source-code of the map in the stl.
If you try doing something similar with an int, you'll get a warning:
int nums[] = { 1, 2, 3, 4, 5 };
for (int i = 0; i < sizeof nums / sizeof *nums; ) {
cout << nums[i] << '\n';
i = i++;
}
warning: operation on 'i' may be undefined [-Wsequence-point]
However, when you're using a class (std::map::iterator) which has operator overloading, the compiler probably isn't smart enought to detect this.
In other words, what you're doing is a sequence point violation, so the behavior is undefined behavior.
The post-increment operation would behave like this:
iterator operator ++ (int) {
auto copy = *this;
++*this;
return copy;
}
So, what happens to your increment step is that iterator it would get overwritten by the copy of its original value. If the map isn't empty, your loop would remain stuck on the first element.
Related
So i have a class in which there is a shared_ptr declared as following
std :: shared_ptr< T > dyn_arr{ new T[ dyn_arr_max_size ], std :: default_delete< T[] >() };
This points to the dynamic array of some size.
I also implemented an iterator for it. Inside this iterator there is a ++ overloaded operator. Now when i get
shared_ptr<T> ptr_iter= dyn_arr;
for example it will work for the first one or two elements. After that it does not iterate properly. Also i notices the following:
For example my ptr_iter is address ABDC0 for ptr_iter.get() in the beginning
After doing
ptr_iter = std :: make_shared<T>( *(ptr.get() + 1 ) );
or
ptr_iter = std :: make_shared<T>( ptr.get()[1] );
ptr_iter.get() will point to some other address now like SDBC instead of pointing to ABDC4 for integers for example. Can someone please explain me why is this happening???
I need to be able to do ptr_iter = make_shared( ptr_iter.get() + 1 ); somehow instead of ptr_iter = make_shared( *(ptr_iter.get() + 1) );
std::make_shared allocates new memory, which you don't want. To solve this problem just use the constructor of std::shared_ptr and pass the adress of the element in the array. However, std::shared_ptr attempts to deallocate as soon as the reference count falls to zero, and you will call delete on an element of the array. That's why you'll need to pass a custom delete which does nothing:
std::shared_ptr<int> ptr_iter{dyn_arr.get() + 1, [](int* pi) {}};
// ^-- Custom deleter does nothing
Example in a loop:
for (int i = 0; i < 9; ++i) {
std::shared_ptr<int> ptr_iter{dyn_arr.get() + i, [](int* pi) {}};
std::cout << *ptr_iter.get() << std::endl;
}
However, I strongly recommend to not do this in other cases than in your assignment!
This problem asks me about a possible number I could replace HUH? with so that it prints hello world and then terminates without any errors.
I tried to figure out the address of x in the main function and used some hexadecimal subtraction between the local variable x in the doit function and the address of x in the main function, but no avail. Is there a way for me to perhaps access the contents of the x in the main function and change that value to 0?
Doing so would cause the while loop to stop running and print out "Hello World".
Is this a feasible approach?
void doit(void) {
int x[1];
x[HUH ? ] = 0;
}
int main(void)
{
int x = 1;
while (x > 0)
{
doit();
}
printf("hello world");
}
No. The only valid index inside x is 0. Any other would trigger undefined behaviour by out-of-bounds access, and x is not used otherwise so you won't get any side-effect out of it.
For example, Clang 7 on Godbolt completely ignores the access and optimizes doit to a simple ret in all cases.
Unless, of course, you cram the side effect into the index expression:
x[std::printf("hello world"), std::exit(0), 0] = 0;
I am using the type std::valarray<std::valarray<double>> and wish to sum each of the contained valarrays element wise, to leave a std::valarray<double>.
The C++ documentation states that the operator .sum() can be applied to std::valarray<T> so long as the operator += is defined for type T. My code below (method1) tries to apply this to std::valarray<std::valarray<double>>, but the result appears to be nonsense.
However if I perform this manually, using the += operator (method2), I get the result I want. But the fact that method2 works seems to imply that the operator += is defined for the type std::valarray<double>, and hence that method1, using .sum(). should work. I really can't understand what is happening here...
My code:
#include <iostream>
#include <valarray>
// Attempt to use .sum() operator
std::valarray<double> method1(const std::valarray<std::valarray<double>>& data) {
return data.sum();
}
// Manual summation using += operator
std::valarray<double> method2(const std::valarray<std::valarray<double>>& data) {
std::valarray<double> sum(data[0].size());
for (size_t i{0}; i < data.size(); i++) {
sum += data[i];
}
return sum;
}
// Display size and elements
void showData(const std::valarray<double> data) {
std::cout << "Size = " << data.size() << "\n";
std::cout << "Data = ";
for (size_t i{0}; i < data.size(); i++) {
std::cout << data[i] << " ";
}
std::cout << "\n\n";
}
int main() {
std::valarray<std::valarray<double>> data{{1,2},{3,4}};
showData(method1(data));
showData(method2(data));
}
My output:
Size = 0
Data =
Size = 2
Data = 4 6
The sum method of std::valarray requires operator+= to be defined for its value type (in your case, std::valarray), but std::valarray also requires it to be default-constructible (from the "Numeric" concept requirement).
This allows the sum method to work without operator+, by first default-constructing an element, and then adding each contained element with operator+=.
Although it isn't defined anywhere, as far as I know, it probably works something like this.
T sum() const {
T result;
for (auto& it : elements) {
result += it;
}
return result;
}
The problem with a valarray of valarrays (std::valarray<std::valarray>) is that a default-constructed valarray is empty. And when operator+= is applied with an empty valarray and a non-empty one, it results in undefined behavior ("The behavior is undefined if size() != v.size()"). What you are likely to get is an empty valarray as a result (but you could potentially get anything).
What you could use instead is std::accumulate. It requires an initial value as third parameter, which takes care of the problem.
std::accumulate(std::begin(data), std::end(data), std::valarray<double>(data[0].size()))
Live on Coliru.
PS: don't ask me why std::valarray has no method begin and end.
In visual studio 2013, I created a std::vector and has store some strings in it. Then I want to make a copy of some string in the vector and append them to the end (suppose to move them to the end, after insert will do erase), but using insert method, I saw only empty strings at the end, very strange. I reproduced it with some simple test code,
std::vector<std::string> v;
std::string s = "0";
for (int i = 0; i < 7; ++i)
{
s[0] = '0' + i;
v.push_back(s);
}
v.insert(v.end(), v.begin(), v.begin() + 3);
for (std::string& s : v)
std::cout << "\"" << s.c_str() << "\" ";
What I get there is
"0" "1" "2" "3" "4" "5" "6" "" "" ""
I debugged into insert method, inside _Insert(..) method of vector class, it did some reallocating of memory, memory move/move and so on.
The first _Umove call move all 7 strings to new allocated memory, I think the std::move is invoked, the old memory has some empty string left.
Then the _Ucopy method try copy 3 items, but from old memory, as a result 3 empty string is attached.
There is another _Umove call, I am not sure what's that for. After all thes, the old memory is freed and new memory attached to the vector.
Using a scalar type like int does not make wrong output, because the memory is copied, no std::move is invoked.
Am I doing something wrong here, or is it a MS Visual Studio's STL bug?
From this std::vector::insert reference:
Causes reallocation if the new size() is greater than the old capacity(). If the new size() is greater than capacity(), all iterators and references are invalidated
[Emphasis mine]
You are adding elements to the vector while iterating the vector using iterators. Since this can cause the vector to be reallocated your iterators will be invalidated. That will lead to undefined behavior.
I was reading C# 4 in a Nutshell and I've come to this piece of code:
IQueryable<Product> SearchProducts (params string[] keywords)
{
IQueryable<Product> query = dataContext.Products;
foreach (string keyword in keywords)
{
string temp = keyword;
query = query.Where (p => p.Description.Contains (temp));
}
return query;
}
Right after the code there's a 'warning' that goes like this:
The temporary variable in the loop is required to avoid the outer variable trap, where the same variable is captured for each iteration of the foreach loop.
I don't get it, I don't understand why the temp variable is necessary. What is the outter variable trap?
From: http://www.albahari.com/nutshell/predicatebuilder.aspx
Can anybody please clarify this?
Because there is only one variable called keyword that is closed over. The temporary variable, however, is different each iteration.
Thus, without the temporary variable, when the lambda is executed later, keyword evaluates to the last value it was assigned in the loop.
Another solution, in some cases, is to force the evaluation (and end up with a List or such).
The problem is that keyword is changing. The => delegate closes on the current value of the variable, not the value it had back in the past when the delegate was created. There's a detailed explanation in Eric Lippert's blog post.
This classic C bug is the same mistake:
#include <stdio.h>
#include <pthread.h>
void * MyThreadFunction(void *x)
{
printf("I am thread %d\n", * (int *) x);
return NULL;
}
int main(void)
{
int i;
pthread_t t[10];
void *ret;
for(i=0; i<10; i++)
pthread_create(&t[i], NULL, MyThreadFunction, (void *) &i);
for(i=0; i<10; i++)
pthread_join(t[i], &ret);
}
The * (int *) x gets the current value of i, not the value when the thread was created.