2

A "Singular Iterator" is defined as an:

iterators that are not associated with any sequence. A null pointer, as well as a default-constructed pointer (holding an indeterminate value) is singular

My question 1 would be: Is a default constructed iterator considered a "Singular Iterator"?

Secondly, I have been told here that:

Results of most expressions are undefined for singular values; the only exceptions are destroying an iterator that holds a singular value, the assignment of a non-singular value to an iterator that holds a singular value, and, for iterators that satisfy the DefaultConstructible requirements, using a value-initialized iterator as the source of a copy or move operation.

Question 2 is: Does working with a result that is "undefined" constitute Undefined Behavior? It would seem that if that were true this would be Undefined Behavior:

void* foo = nullptr;
auto bar = foo;

But it runs fine.


My deeper motivation for asking this question is in the case where I have a struct like this:

struct Foo {
    vector<int*>::const_iterator;
};

I want to know if it is undefined behavior to do this, where assigned is a value constructed Foo object:

Foo unasigned;

assigned = unassigned;

If the answers to questions 1 and 2 are "yes" then by invoking the default assignment operator I am introducing undefined behavior :(

Community
  • 1
  • 1
Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288
  • 1
    Just a side note: It's not because it run fine somewhere that this is not an UB – Thomas Ayoub Sep 24 '15 at 11:45
  • What do you mean by 'a default constructed iterator'? – CinCout Sep 24 '15 at 11:48
  • You should include the code that you're actually asking about, rather than making vague statements. – Barry Sep 24 '15 at 11:48
  • @HappyCoder `vector::const_iterator foo;` is what I'm referring to when I say "default constructed iterator". – Jonathan Mee Sep 24 '15 at 11:50
  • @Barry I've added a minimal example. – Jonathan Mee Sep 24 '15 at 11:55
  • 2
    That paragraph imposes general requirements on iterators - i.e., they are not required to support operations with singular values beyond those specified. A concrete iterator type (such as a pointer) may offer additional guarantees. For `vector::const_iterator`, it's an implementation-defined type, and you can't assume that it does anything more than what the standard requires. – T.C. Sep 25 '15 at 19:07

2 Answers2

0

Question 2 is: Does working with a result that is "undefined" constitute Undefined Behavior?

Answer is: Definitely Yes. Working on UB is UB.

It seems to run fine for you since it is undefined. It can do anything, this includes working as expected, as well as working not as expected.

CinCout
  • 9,486
  • 12
  • 49
  • 67
0

Regarding the example for the second question, it works fine because and is well-defined, because you don't actually dereference the pointer foo. The variable foo is initialized, all you are doing is initializing a variable with another initialized variable. It's no different from e.g.

int foo = 0;
auto bar = foo;

However, if you did e.g.

int* foo = nullptr;
auto bar = *foo;

that would be UB because you dereference a null pointer.

Also, Undefined behavior is, well, undefined... It might seem to run fine but in reality it's really not.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • Right and I don't need to dereference the contents of the `vector::const_iterator` member of my struct so I'd assume that means it's well defined as well? – Jonathan Mee Sep 24 '15 at 11:48
  • 1
    @JonathanMee That's correct, if you have a default-initialized iterator, it's still *initialized* and you can use it as a source for an assignment. It's when you attempt to perform any other operation (which includes more than just dereferencing) that you get UB. – Some programmer dude Sep 24 '15 at 11:50
  • I want to believe that statement cause it simplifies a lot of my issues in code. But that statement is in conflict with the second quote I have in the question though isn't it? (Though maybe that quote is obsolete? I just read this: http://en.cppreference.com/w/cpp/concept/ForwardIterator#Singular_iterators) – Jonathan Mee Sep 24 '15 at 11:59
  • 1
    @JoachimPileborg No. In `int *x, *y;`, `x` is default-initialized, but `y = x;` is UB by the applicable core-language rules. This is why the iterator clause requires value-initialized iterators. – T.C. Sep 25 '15 at 19:03