• Create Account

### #ActualAntheus

Posted 03 May 2012 - 05:39 AM

My problem here is that I never figured out that the compiler would have cast something in the first place and yes, it was clear to me there were different types going to clash.

It's not a cast, it's implicit conversion.

Going back to string example:
void foo(const string & str);

const char * s;
foo(s);
Obviously, s cannot be passed to str, they are unrelated types.

But string has a constructor which takes const char *.

So compiler creates new string by passing s into its constructor. This is the temporary object. Same thing happens with lambdas - a new function<> instance is created as temporary.

Which is why it's recommended to declare constructors with 'explicit' to prevent these accidental conversions. String doesn't use explicit to work transparently with C-style strings. Otherwise, one would need to manually perform the conversion:
foo(std::string(s)); // which is potentially ambiguous as function call
// so
std::string temp(s);
foo(temp);
// vs
foo("Hello World");

As a side note I still don't quite understand why references cannot be copied.

They can be, but don't produce desirable result. Simple example, using pointers to make it clearer:
struct A {
int * x;
}

A a;
a.x = new int(10);

A b;
b.x = a.x; // wrong
delete a.x; // boom
---
b.x = new int( *a.x); // right, deep copy
delete a.x; // no problem


It is impossible to properly implement assignment operator or rule of three with references alone - and there is no mechanism to provide a deep copy, since references don't provide life cycle information. Even if they did, it wouldn't help, since they might refer to read-only storage, stack, part of another structure, heap or just about any other valid memory location, many of which cannot be copied, but can be destroyed.

### #1Antheus

Posted 03 May 2012 - 05:37 AM

My problem here is that I never figured out that the compiler would have cast something in the first place and yes, it was clear to me there were different types going to clash.

It's not a cast, it's implicit conversion.

Going back to string example:
void foo(const string & str);

const char * s;
foo(s);
Obviously, s cannot be passed to str, they are unrelated types.

But string has a constructor which takes const char *.

So compiler creates new string by passing s into its constructor. This is the temporary object. Same thing happens with lambdas - a new function<> instance is created as temporary.

Which is why it's recommended to declare constructors with 'explicit' to prevent these accidental conversions. String doesn't use explicit to work transparently with C-style strings. Otherwise, one would need to manually perform the conversion:
foo(std::string(s)); // which is potentially ambiguous as function call
// so
std::string temp(s);
foo(temp);
// vs
foo("Hello World");

As a side note I still don't quite understand why references cannot be copied.

They can be, but don't produce desirable result. Simple example, using pointers to make it clearer:
struct A {
int * x;
}

A a;
a->x = new int(10);

A b;
b->x = a->x; // wrong
delete a->x; // boom
---
b->x = new int( a->x); // right
delete a->x; // no problem


It is impossible to properly implement assignment operator or rule of three with references alone - and there is no mechanism to provide a deep copy.

PARTNERS