Conversation
| @@ -21,14 +21,13 @@ class Student { | |||
|
|
|||
| Student* getStudent(){ | |||
| Student* myStudent = new Student(10801983,"Mary Wright"); | |||
There was a problem hiding this comment.
given this new statement and seeing no delete anywhere this code has a memory leak.
|
|
||
| void iteratorLoop(std::vector<Tool>& tools){ | ||
| for(std::vector<Tool>::const_iterator tool = tools.begin(), end = tools.end(); tool != end; ++tool){ | ||
| for(auto tool = tools.begin(), end = tools.end(); tool != end; ++tool){ |
There was a problem hiding this comment.
auto tool creates an unecessary copy of each object. Did you consider references?
In addition the const_iterator is const, while auto alone does not preserve constness.
There was a problem hiding this comment.
What exactly does auto tool copy? The input vector itself is already passed by reference.
How can tool be const when it is incremented? Supposedly const_iterator implies the target to be const, which is not consistent with the declaration of the function input.
There was a problem hiding this comment.
What you get in hand is the object, not an iterator to it. auto tool copies every single tool you are looping over. auto& tool would prevent that.
And as you are dealing with the object and not an iterator, it can as well be const.
There was a problem hiding this comment.
The iterator increment ++tool does not work with const, auto seems to favour the normal iterator structure over const_iterator.
There was a problem hiding this comment.
ah. sorry. you are right. I was having a different example in my head :-)
modernsyntax/classical_looping.cpp
Outdated
| void rangeLoop(std::vector<Tool>& tools, const int beginning, const int ending){ | ||
| auto tool = tools.begin(); | ||
| std::advance(tool,beginning); | ||
| for(auto end = tools.end(); std::distance(tool, end) > std::distance(tools.begin(), end) - ending; ++tool){ |
There was a problem hiding this comment.
Here std::distance is being calculated during every loop step. Is there a more performant way?
There was a problem hiding this comment.
The second distance could definitely be stored. The first one might behave differently if the loop content alters the size of tools or shifts tool. For our simple print this is of course no concern so a full pre-calculation would be more efficient.
modernsyntax/lambda.cpp
Outdated
| // launch a thread to increment the counter | ||
| std::thread increment(incrementCounter,&counter,100000); | ||
|
|
||
| std::thread increment([](int* counter, const unsigned int times){for (unsigned int i=0; i<times;++i){++(*counter);}},&counter,100000); |
There was a problem hiding this comment.
The number of iterations one could as well try to catch by value in the [] part of the lambda.
There was a problem hiding this comment.
Can that syntax catch an argument passed by std::thread or would this require a pre-initialisation of a variable to catch? At the very least a variable initialisation adds another line of code where, to my understanding, the current implementation does not sacrifice performance.
There was a problem hiding this comment.
To put your point to the extreme - if you specify that number in the same line as the lambda, you don't even need it as extra function parameter of the lambda ;-) Thus having an extra variable seems to better match the lambda definition. Nevertheless the current code is correct.
There was a problem hiding this comment.
Which means the "better" solution depends on the intended purpose of the count. An external variable is "future-proof" for end-user input while a deliberately hardcoded value is easier to track within the function definition. Passing a fixed value as an argument as in the current version would only be desirable if it is reused multiple times within the function, correct? (then again such a function probably should not be an inline lambda to begin with)
There was a problem hiding this comment.
Nothing to add to that analysis :-)
…ounter' directly in the inline lambda
modernsyntax/lambda.cpp
Outdated
|
|
||
| std::thread increment([](int* counter, const unsigned int times){for (unsigned int i=0; i<times;++i){++(*counter);}},&counter,100000); | ||
| const unsigned int times = 100000; | ||
| std::thread increment([×](int* counter){for (unsigned int i=0; i<times;++i){++(*counter);}},&counter); |
There was a problem hiding this comment.
would have taken it by value, but OK
| int main(){ | ||
| Student* myStudent = getStudent(); | ||
| printStudent(myStudent); | ||
| delete myStudent; |
There was a problem hiding this comment.
you could have used a smart pointer here.
There was a problem hiding this comment.
Is there a way to do this without overwriting all standard pointer usage in the code? Initialising as a smart pointer type breaks printStudent as it expects a raw pointer as input.
There was a problem hiding this comment.
This may help: http://en.cppreference.com/w/cpp/memory/unique_ptr/get
Modified source code for the "modern C++" exercises (except smart_pointers) and the "debugging" exercise. The rangeLoop function added in classical_looping.cpp contains a "Python range"-style start and stop input.