I have a struct that contains an int but when I call the following...
typedef std::map<char, MessageLetter> Letters;
...
Letters lList;
...
MessageLetter m = lList[letter];
std::cout << "Before " << m.count << std::endl;
int c = ++m.count;
m.count = c;
std::cout << "After " << m.count << std::endl;
I am new to C++ and I am guessing this is a pointer issue but the output is...
Before 1
After 2
Before 1
After 2
I would expect...
Before 1
After 2
Before 2
After 3
I think you actually want:
MessageLetter & m = lList[letter];
I'm assuming this statement is part of a body of a loop:
MessageLetter m = lList[letter];
On each iteration of the loop, you're copying alList[letter] into m. Any modifications to m will be lost after the loop iteration completes. You will not modify lList[letter].
If you want to modify lList[letter], you either need to modify it directly, or make m a reference to it:
MessageLetter& m = lList[letter];
If you do not want to modify lList[letter], then you need to move the above assignment outside the loop to someplace above the loop.
Related
The example I talked about is this one on cppreference.com.
The code snippet is pasted below.
int main(){
const std::size_t ThreadNumber = 5;
const int Sum = 5;
std::atomic<int> atom{0};
std::atomic<int> counter{0};
// lambda as thread proc
auto lambda = [&](const int id){
for (int next = 0; next < Sum;){
// each thread is writing a value from its own knowledge
const int current = atom.exchange(next);
counter++;
// sync writing to prevent from interrupting by other threads
std::osyncstream(std::cout)
<< '#' << id << " (" << std::this_thread::get_id()
<< ") wrote " << next << " replacing the old value "
<< current << '\n';
next = std::max(current, next) + 1;
}
};
std::vector<std::thread> v;
for (std::size_t i = 0; i < ThreadNumber; ++i){
v.emplace_back(lambda, i);
}
for (auto& tr : v){
tr.join();
}
std::cout << ThreadNumber << " threads adding 0 to "
<< Sum << " takes total "
<< counter << " times\n";
}
To me, the value of counter is 25 because 5 threads and each thread loops 5 times. However, the shown output is 16. I also ran it myself, the possible value varies, but it never gets to be 25.
Why the printed value of counter is actually smaller?
Consider one of the possible executions:
Lets say one of the threads finishes the loop before other threads start.
This gives you atom == 4. The next thread to enter the loop will get current == 4 and will exit the loop after the first iteration.
This way the second thread increments current once instead of 5 times like you expect it to.
I haven't taken the trouble to analyse the code in detail, but the for loop in the lambda is broken (or, at least, not doing what you are expecting it to do). If you replace it with something more straightforward, namely:
for (int next = 0; next < Sum; ++next){
then 25 is output.
#define prod(a) (a*a)
using namespace std;
int main()
{
int i = 3, j, k, l;
j = prod(i++);
cout << i << endl;
k = prod(++i);
cout << i << endl;
l = prod(i+1);
cout << i << " " << j << " " << k << " " << l;
}
Why is variable "i" incremented twice?
i.e to 5 from 3 after j=prod(i++);
Remember that macros are expanded in the source code, not actually called or evaluated.
That means a "call" like
prod(i++)
results in the expanded code
i++*i++
being seen by the compiler.
Many compilers allow you to stop after preprocessing, or otherwise generate preprocessed source, that you can examine to see macro expansions.
If you continue using such a macro with other expressions as arguments, you will soon see another reason they are bad.
Lets say you use
prod(2+4)
Then that will result in the expansion
2+4*2+4
which is equal to
2+(4*2)+4
which is equal to 14, not 36 which might have been expected.
Why is variable "i" incremented twice? i.e to 5 from 3 after j=prod(i++)
Because prod() is a macro, not a function, so
k=prod(++i);
become
k=(++i * ++i);
I am trying to delete the consecutive duplicate characters from a string such as "helloworld" and delete all occurrences of the duplicate character. In this case, it is 'l', so the new string should be "heoword". I have written the code like this:
#include <algorithm>
#include <string>
#include <iostream>
using namespace std;
int main() {
string s = "helloworld";
for (int i = 0; i < s.length() - 1; i++) {
if (s[i] == s[i+1]) {
s.erase(remove(s.begin(), s.end(), s[i]), s.end()); // PROBLEM
cout << s << endl; // printing `heowrld`, instead of `heoword`
}
}
return 0;
}
The code above doesn't work unless I cast s[i] like (char)s[i]. I looked up the operator [] for the string and it is returning the reference to the character at position. The remove method also accepts const T& val as parameter for character to be replaced. Since both of them are of the same type, why can't I just put in s[i] as argument to the remove method?
p.s. This is not homework problem. By casting the s[i] in remove, I can get correct output but I would like to know why I need to cast s[i].
The problem here is your moving the value to remove out from under yourself. Lets look at
#include <iostream>
int main()
{
int a = 5, b = 10;
int & ref = a;
std::cout << "a: " << a << " b: " << b << " ref: " << ref << "\n";
std::swap(a, b);
std::cout << "a: " << a << " b: " << b << " ref: " << ref << "\n";
}
If you run it you will get
a: 5 b: 10 ref: 5
a: 10 b: 5 ref: 10
and as you can see ref doesn't move to now follow b but stays with a (as it should) and prints a's new value.
We are seeing the same thing with
s.erase(remove(s.begin(), s.end(), s[i]), s.end());
Since s[i] is a reference to an element in the string its value gets changed as remove swaps the elements around. So it removes both l's and then it also removes the last o since o is moved into the same position that l used to occupy but it only does so after it passed the first o in the string.
The reason casting "fixes" this is because now you are no longer referring to an element of the string. You create a temporary variable and you use that variables value to remove the l's.
Why is the output of statement 2 different from that of statement 1?
// a is of type vector < tuple <int, int> >
for (auto i: a)
{
get<0>(i)+=get<1>(i);
cout << get<0>(i) << " " << get<1>(i) << endl; // 1
}
for (auto i: a) cout << get<0>(i) << " " << get<1>(i) << endl; // 2
Suppose that initially, a contains [7, 3] , [9, 1]
Then 1 outputs
10 3
10 1
whereas 2 outputs
7 3
9 1
In short, the loop enclosing statement 1 seems to have no effect.
I think it has something to do with my usage of auto and not using *i to change the value, but I don't think that we can use *i in get.
Because when you do:
for (auto i: a)
you're making copies of every element in a. You're iterating by value and modifying local copies of the elements of the container. If you want to actually modify elements of the container, you have to iterate by reference:
for (auto& i : a)
^^^
auto does not deduce reference.
Yes, your suspicion is correct, in for (auto i: a) the i contains a copy of the tuple. Any changes affects the copy only.
You can use for (auto& i: a) to make changes that affects the "original" tuple.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Undefined Behavior and Sequence Points
I'm having trouble understanding the order of actions when overloading the postfix operator. Let's examine the two small examples below:
int i = 0;
std::cout << std::endl << "i: " << i;
i = ++i;
std::cout << std::endl << "i: " << i;
i = i++;
std::cout << std::endl << "i: " << i;
MyClass myObject;
std::cout << std::endl << "myObject: " << myObject.getMyValue();
myObject = ++myObject;
std::cout << std::endl << "myObject: " << myObject.getMyValue();
myObject = myObject++;
std::cout << std::endl << "myObject: " << myObject.getMyValue();
Two very different behaviors emerge. The output is as follows:
i: 0
i: 1
i: 2
myObject: 0
myObject: 1
myObject: 1
Different behavior, you see. Here's the outline of my overloaded-operator methods.
MyClass & MyClass::operator++ ()
{
++myValue;
return *this;
}
MyClass MyClass::operator++ (int postfixFlag)
{
MyClass myTemp(*this);
++myValue;
return myTemp;
}
Alright. Prefix makes sense. You increment whatever you need to, then return the same object, now modified, in case of assignment. But postfix is what's tripping me up. It's supposed to assign, then increment. Here we're self assigning. So with the built-in integer type, it makes sense. I assign i's value to itself, then i gets incremented. Fair enough. But let's say MyClass is a recreation of the int. It starts out at 0, gets prefix-incremented, and becomes 1. Then, the key line. myObject = myObject++. That's the same thing as myObject = myObject.operator++(int postfixFlag). It gets called. myTemp gets initialized with the value 1. It's incremented to 2. Then we return the temp. That works, if we're assigning to another object. But here I'm self-assigning, so after the increment to 2, myObject is set equal to the returned temp object initialized with the initial value, and we're back to 1! That makes sense. But it's a fundamentally different behavior.
How do I work around it? How does int do it? How is this method generally written? Do you have any comments about C++ behavior and design relating to this? Etc. I'm a little perplexed right now, since books and online examples always seem to use a variant on the method above.
Thanks for reading, and any input will be appreciated!
As others have said, with int the behaviour is undefined. But I thought I'd try to explain why for your MyClass it is not ever getting to 2.
The trick is that you are taking the following three steps in the postfix version:
Making a copy of this called myTemp (with myValue == 1).
Incrementing this->myValue (so myTemp.myValue == 1; this->myValue == 2).
Returning myTemp (with myValue == 1).
So you are modifying this, but the code that calls myObject++ is never going to see this again. It's only going to look at the value returned, which is a copy of the old myObject.
The code for operator++ is fine. The problem is how you are using it -- you shouldn't be writing the result of a pre-increment or post-increment back to the same variable (behaviour is undefined). Here is some code that might be more instructive:
int i = 0;
std::cout << "i: " << i << std::endl;
int j = ++i;
std::cout << "i: " << i << ", j: " << j << std::endl;
int k = i++;
std::cout << "i: " << i << ", k: " << k << std::endl;
MyClass myObject;
std::cout << "myObject: " << myObject.getMyValue() << std::endl;
MyClass myObject1 = ++myObject;
std::cout << "myObject: " << myObject.getMyValue()
<< ", myObject1: " << myObject1.getMyValue() << std::endl;
MyClass myObject2 = myObject++;
std::cout << "myObject: " << myObject.getMyValue()
<< ", myObject2: " << myObject2.getMyValue() << std::endl;
This prints:
i: 0
i: 1, j: 1
i: 2, k: 1
myObject: 0
myObject: 1, myObject1: 1
myObject: 2, myObject2: 1
I changed your code so that rather than assigning back to itself, it assigns to a fresh variable each time. Note that in both the int and the MyClass cases, the main variable (i/myObject) is incremented both times. However, in the pre-increment case, the fresh variable (j/myObject1) takes on the new value, while in the post-increment case, the fresh variable (k/myObject2) takes on the old value.
Edit: Just answering another part of the question, "How does int do it?" I assume this question means "what does the pre-increment and post-increment code look like in the int class, and how can I make mine the same?" The answer is, there is no "int class". int is a special built-in type in C++ and the compiler treats it specially. These types aren't defined with ordinary C++ code, they are hard-coded into the compiler.
Note: For anyone who wants to try this themselves, here is the code for MyClass that the question didn't include:
class MyClass
{
private:
int myValue;
public:
MyClass() : myValue(0) {}
int getMyValue() { return myValue; }
MyClass& operator++();
MyClass operator++(int postfixFlag);
};