As seen on ideone:
cout << string(50, 'x'); // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
cout << string{50, 'x'}; // 2x
WAT??
I have figured out that 50 is ASCII '2', so:
cout << static_cast<int>('2'); // 50
cout << static_cast<char>(50); // 2
But that's as far as I've got.
Does this lead to a solid argument against C++11 initializers?
When you do string { 50, 'x' } you're essentially initializing the string with a list of characters.
On the other hand, string(50, 'x') calls a 2 argument constructor, which is defined to repeat the character x 50 times. The reason why string { 50, 'x' } doesn't pick the constructor is that it could be ambiguous. What if you had a three parameter constructor as well? If the type has an initializer_list constructor, it will be picked when you use { ... } for initialization.
Basically you need to be aware of the constructors your type has. The initializer_list constructor will always have a precedence to avoid ambiguity.
Related
I am trying to learn the concept of closures in C++. I have the following code.
std::function<void(void)> closureWrapper2()
{
int x = 10;
return [&x](){x += 1; std::cout << "Value in the closure: " << x << std::endl;};
}
int main()
{
std::function<void(void)> func2 = closureWrapper2();
// std::cout << "---" << std::endl;
func2();
func2();
func2();
}
Output
Value in the closure: 11
Value in the closure: 12
Value in the closure: 13
Now if I uncomment the cout statement I get the following output.
Output
---
Value in the closure: 32765
Value in the closure: 32766
Value in the closure: 32767
Can anyone please explain why printing something before the function calls changes the output?
std::function<void(void)> closureWrapper2()
{
int x = 10;
return [&x](){x += 1; std::cout << "Value in the closure: " << x << std::endl;};
}
It's undefined behaviour(a) to dereference a pointer to, or use a reference to, an object after that object no longer exists. That's what you're doing here. You capture a reference to x then attempt to use it after x has ceased to exist.
It's a local (automatic storage duration) variable inside closureWrapper2() so ceases to exist when that function exits.
That may appear to work without the cout line but that doesn't make it any less undefined. Putting the cout line is almost certainly modifying the stack where x was originally stored, changing the starting value.
You can get a similar effect with (in my environment):
void otherFn() { int abc = 97, def = 42, ghi = 9; std::cout << abc+def+ghi << '\n'; }
int main()
{
std::function<void(void)> func2 = closureWrapper2();
otherFn();
func2();
func2();
func2();
}
This indicates that the original value is definitely being overwritten by the abc variable in otherFn():
148
Value in the closure: 98
Value in the closure: 99
Value in the closure: 100
I had to try varying numbers of arguments as the stack frames for the closureWrapper2() and otherFn() are most likely different. Calling cout.operator<<() is likely to go through a number of stack levels to achieve its end so will be more likely to overwrite the original value.
(a) This is the solution to your problem, of course: don't do undefined behaviour :-)
The program below is outputting unexpected use_count() value when shared pointer is printed using iterator de-reference of std::vector:
#include<iostream>
#include<memory>
#include<vector>
class A;
typedef std::shared_ptr<A> sharedPtr;
typedef std::vector<sharedPtr> sharedPtrVect;
typedef sharedPtrVect::const_iterator vectItr;
class A
{
public:
A(int inp): m_Val(inp) { /*std::cout << "*** A ctor called: " << m_Val << " ***" <<std::endl;*/ }
~A() { /*std::cout << "### A dtor called: " << m_Val << " ###" <<std::endl; */}
int getVal() const { return m_Val; }
private:
int m_Val;
};
int main()
{
sharedPtrVect myVect1, myVect2;
vectItr myVectItr;
std::shared_ptr<A> tmpPtr;
for(int i = 1 ; i <= 5 ; i++ ) {
std::cout << "Pushed back: " << i << std::endl;
tmpPtr = std::make_shared<A>(i);
myVect1.push_back(tmpPtr);
}
myVectItr = myVect1.begin();
for( ; myVectItr != myVect1.end() ; ++myVectItr) {
std::cout << "-----------------------------" << std::endl;
std::cout << "Element number: " << (*myVectItr).get()->getVal() << std::endl;
std::cout << "Element use count: " << (*myVectItr).use_count() << std::endl;
std::cout << "-----------------------------" << std::endl;
}
return 0;
}
The output of the above code is:
Pushed back: 1
Pushed back: 2
Pushed back: 3
Pushed back: 4
Pushed back: 5
-----------------------------
Element number: 1
Element use count: 1
-----------------------------
-----------------------------
Element number: 2
Element use count: 1
-----------------------------
-----------------------------
Element number: 3
Element use count: 1
-----------------------------
-----------------------------
Element number: 4
Element use count: 1
-----------------------------
-----------------------------
Element number: 5
Element use count: 2 //I am not sure why or how this is 2?
-----------------------------
I don't understand how the use_count() for the last vector element is 2. Shouldn't it be 1 like others? I am not creating any copies of the shared pointer stored in the last element of the vector.
What am I missing here?
EDIT: I have good experience in C++98, but less experience in C++11.
Shouldn't it be 1 like others? I am not creating any copies of the shared pointer stored in the last element of the vector. What am I missing here?
But you are creating a copy. You push_back() from tmpPtr. push_back() puts a copy of its argument into the vector, unless you tell it to move instead. (More on that later!)
Therefore, what happens for all but the last element is this:
tmpPtr holds the only reference to the shared resource
You push_back() a copy, so the copy-constructor of shared_ptr increments the use count to 2
You then assign the next element to tmpPtr, releasing the reference to, and thereby decrementing the use count of, the previous element's resource.
But, of course, there is no subsequent assignment on the last iteration of the loop. So, at the point of printing, tmpPtr is still in scope, and it retains a reference to the last resource that was allocated. Hence the 1-higher refcount on the last element. This seems perfectly expected to me. ;)
To see the results you expected, you need to either destroy tmpPtr after you copy it but before you print, or simply avoid the copy from it in the first place. The former could be done by moving its declaration into the for loop, as SirGuy pointed out in the comments.
However, clearly, the latter is superior. How do we do that? Well, C++11 lets us move instead. So, you could emplace_back( std::move(tmpPtr) ), in which the move will cast to an rvalue and thus invoke the move-constructor of the vector element. This will cause tmpPtr to release its reference upon being moved into the vector, effectively ensuring the use count is always 1. This leaves tmpPtr (like any moved-from object) in a valid-but-unspecified state, i.e. useful only to be reassigned-to.
(Note: push_back() will achieve the same thing, but I generally prefer using emplace_back() wherever possible, as it's more efficient in other situations, so it's a better default.)
Of course, you can then combine both of these: declare tmpPtr within the scope of the for loop, and move from it. However... you don't even need tmpPtr at all! It does not appear to serve any useful purpose. So, you could just not use it, and instead directly emplace_back() the result of make_shared(). Because the return value thereof will be an rvalue, it will implicitly be moved into the vector; no cast by std::move is needed.
Is it possible to walk a std::forward_list, incrementing an iterator, until said interator is null? The old-fashioned way...
In the following example, I create a print() function.
#include <iostream>
#include <forward_list>
void print(std::forward_list<int>::iterator fl_it, std::forward_list<int>::iterator e) {
while (fl_it != e) {
std::cout << *fl_it << ' ';
++fl_it;
}
std::cout << std::endl; //-> 1 2 3
}
int main() {
std::forward_list<int> fl = {1, 2, 3};
print(fl.begin(), fl.end());
std::cout << std::endl;
return 0;
}
Notice how passing an iterator pointing to the end of the list is necessary, so that we know when to stop walking.
What I want to do is simply pass an iterator to the head of the list, and step along until there are no more elements, like so:
void print(std::forward_list<int>::iterator fl_it) {
while (fl_it != nullptr) {
std::cout << *fl_it << ' ';
++fl_it;
}
std::cout << std::endl;
}
My compiler doesn't like this fl_it != nullptr business.
My first inclination was to look for a method to check if the iterator is null, and references the end of the list. Sadly, such a method does not exist.
Any ideas?
You don't.
std::forward_list is a standard library container. Like all containers, it goes from begin to end. There are no "null" iterators. Operations therefore are on a range of iterators.
Note that the Range TS proposal intends to allow "sentinel" types instead of requiring end iterators. A single sentinel could compare equal to the end iterator of any range. So forward_list could indeed be updated to have such a value.
But it still wouldn't be a "null" iterator.
You should realise that the iterator object is not exactly a pointer. It is an object and it represents the position of an item in a datastructure.
Also incrementing the end iterator does not result in a null iterator. It is undefined behavior. Look at Can an STL map iterator go out of bounds through incrementing?
The iterator is not null when at the end of the list, instead it is equal to the list's end iterator fl.end(). So both iterators need to be passed to the function.
The internal implementation of the iterator depends on the STL library used, for std::forward_list its interface is such that it fulfills the ForwardIterator concept: http://en.cppreference.com/w/cpp/concept/ForwardIterator .
vector<int> a = { 1,2,3,4,5,6,7 };
pair<vector<int>, vector<int>::iterator> pair_of_itr; //not working showing wrong directional error!
auto pair_of_itr = minmax_element(a.begin(), a.end());
cout << *pair_of_itr.first << " " << *pair_of_itr.second << endl; // working with auto but not with the PAIR of iterator.
//cout << pair_of_itr->first << " " << pair_of_itr->second << endl // not working
return 0;
here i have explained via comments. plz do refer comments.
a->b is the same as (*a).b. *a.b is the same as *(a.b). So they differ in whether a is dereferenced, or a.b is dereferenced.
In your case, auto pair_of_itr = std::minmax_element ... creates a std::pair of iterators, and it is the iterator you want to dereference. So that would be *pair_of_itr.first. *pair_of_itr is ill-formed because a std::pair is not itself a pointer or iterator.
The problem with pair<vector<int>, vector<int>::iterator> pair_of_itr; is simply that the first element of the pair is a std::vector, not a std::vector::iterator. So in that case neither pair_of_itr nor pair_of_itr.first can be dereferenced. *pair_of_itr.second would compile, because the second element is an iterator.
It's usually a good idea to add redundant parentheses, particularly if you needed to ask whether they were necessary. Other people also might not remember that *a.b means *(a.b), and the parentheses don't cost a lot.
I've come across this "feature" in MSVC++ and I'm now not sure if it's a bug or my understanding of lvalues/rvalues in C++ is just plain wrong.
I've added some seriously dumbed-down code to illustrate, but basically the issue is that MSVC++ 2013 (both base and NOV 2013 CTP compilers) allows assignment to temporary objects, which should really be rvalues and hence disallow any assignment attempts at compile time.
#include <iostream>
struct account {
int value;
explicit account(int v) : value{ v } {
std::cout << "account ctor: " << value << std::endl;
}
account(const account & acc) : value{ acc.value } {
std::cout << "account copy ctor" << std::endl;
}
account(account && acc) : value{ acc.value } {
std::cout << "account move ctor" << std::endl;
}
account & operator=(const account & acc) {
value = acc.value;
std::cout << "account copy assign" << std::endl;
return *this;
}
account & operator=(account && acc) {
value = acc.value;
std::cout << "account move assign" << std::endl;
return *this;
}
};
int get_int() { return 42; }
account get_account() {
return account(123);
}
int main() {
//get_int() = 5; // this predictably fails to compile
// with '=' : left operand must be l-value
// everything below succeeds
get_account() = account(42); // console trace for this
// account ctor: 42
// account ctor: 123
// account move assign
account(123) = account(42); // console trace same as above
account acc(0); // account ctor: 0
account(42) = acc; // account ctor: 42
// account copy assign
get_account() = acc; // console trace same as above
}
Surely get_account() = acc; or account(42) = acc; is not C++ Standard's prescribed behaviour?! Both get_account() & account(42) should result in rvalues, which by definition do not allow assignments.
Incidentally, overloading member functions based on lvalue/rvalue qualifiers
...
void memberFn() const &;
void memberFn() &&;
...
which is supported in NOV 2013 CTP is not working properly or at all. I assume this is a result of failing to recognise rvalues, so that this is always an lvalue.
PS Unfortunately, I do not have an opportunity to test this with other compilers.
According to my understanding, this is perfectly valid C++11.
Only built-in assignment to prvalues is prohibited.
From [5, expr]:
Note: Operators can be overloaded, that is, given meaning when applied to expressions of class type (Clause
9) or enumeration type (7.2). Uses of overloaded operators are transformed into function calls as described
in 13.5. Overloaded operators obey the rules for syntax specified in Clause 5, but the requirements of
operand type, value category, and evaluation order are replaced by the rules for function call.
So the requirements on
get_account() = account(42);
are the same as on any other member-function call
get_account().foo_bar(account(42));
which makes sense since it is just a nicer syntax for
get_account().operator=(account(42));
The section 3.10 on Lvalues and rvalues makes this as clear well [basic.lval]:
For example, the built-in assignment operators expect that the left operand is an lvalue and that the right operand is a prvalue and yield an lvalue as the result. User-defined operators are functions, and the categories of values they expect and yield are determined by their parameter and return
types.