Returning local automatic objects from functions

Pages: 12
You're staring down the rabbit hole now. References are significantly more complicated than they appear.

Is there SOMETHING ELSE about this "const" that I don't know?

Perhaps: there's one more important detail that hasn't yet been mentioned. That is, any value category may bind const lvalue references.

This is surprising, because only lvalues may bind to non-const lvalue references, and only rvalues may bind to rvalue references (as the names suggest).

The only difference is that on line 6 the initializer is the result of a function, while on line 7 the initializer is a variable.

More specifically, the difference is the value category. (As @helios mentioned)
The variable is an lvalue. This particular function call expression (f())is an rvalue (a prvalue, specifically.) And as I wrote, a non-const lvalue reference (as is expected by the original operator=) can only bind to lvalues (like the variable named by a), but a const lvalue reference can bind to anything, including rvalues, like that function result.

Edit:
whoops, I didn't read carefully enough
My apologies, @helios
Last edited on
@JLBorges

Thank you for this link.
But this is not "somewhat intimidating", this is downright full blown nightmare !!!!
Somebody please shoot me so I don't have to read all this mess !!! :(
@helios

1. Regarding the copy constructor signature:

I'm not sure what to say here:
A (const A&) is NOT the canonical signature for the copy constructor, at least that's what the course I'm reading says. By the way, I'm talking about the C++ institute.
Here's what they say:

"The copying constructor is a specific form of constructor designed to make a more or less literal copy of an object. You can recognize this constructor by its distinguishable header.
Assuming that a class is called A, its copying constructor will be declared as:

A(A &)

This means that the constructor expects one parameter to be a reference to an object whose content is intended to be copied to the newly created object."

Are they maybe wrong here, in the sense that maybe A ([const] A&) would be the real canonical copy constructor signature?
I mean, does maybe the true theoretical signature specify a "const", but which is optional?
I found myself some mistakes in their course, I just want the truth.

Here's an example program using this signature (A(A &)) for a copy constructor:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>
using namespace std;
class Class {
	int data;
    public:
	Class(int value) {
		cout<<"Constructing "<<value<<endl;
		data = value;
	}
	Class(Class &source) {
		cout<<"Copying\n";
		data = source.data;
	}
	~Class(void) {
		cout<<"Destroying "<<data<<endl;
	}
	void increment(void) { data++; }
	int value(void) { return data; }
};
int main(void) {
	Class o1(123);
	Class o2 = o1;
	Class o3(o2);
	o1.increment();
	cout << o1.value() << endl;
	cout << o2.value() << endl;
	cout << o3.value() << endl;
	return 0;
}


The program works fine and the output I get is this:

1
2
3
4
5
6
7
8
9
10
11
12
user:~$ g++ -fno-elide-constructors -o test test.cpp 
user:~$ ./test
Constructing 123
Copying
Copying
124
123
123
Destroying 123
Destroying 123
Destroying 124
user:~$



2. Regarding the "a" variable:

Yes "a" is an L-VALUE, but any L-VALUE is ALSO an R_VALUE.
That's why I said in both cases a non-const reference is being initialized from an rvalue.
But I see now this lvalue-rvalue issue is not exactly as straight-cut as I thought.
I will have to do a lot more reading... :(
@mbozzi

Thank you for this explanation.
Just when I thought I had everything figured out, I tackled Little Captain's code which opened up this whole can of worms!

So right now I'm not staring down the rabbit hole.
I'm staring down the Hell hole !
For starters, use this simplified definition of lvalue.
We assume that the unary & (addressof) operator is the built in & operator, and we ignore move semantics for now.

If e is an expression and &e is syntactically correct (ie, if we can determine the address of the object),
then the value category of e is lvalue.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include <cstring>

int main()
{
    int i = 10 ;

    int* pm = &i ; std::cout << &*pm << '\n' ; // *pm is an lvalue
    int& rm = i ; std::cout << &rm << '\n' ; // rm is an lvalue

    const int* pc = &i ; std::cout << &*pc << '\n' ; // *pc is an lvalue
    const int& rc = i ; std::cout << &rc << '\n' ; // rc is an lvalue

    const auto pf = &std::strlen ; // fine: std::strlen is an lvalue

    &(i+3) ; // **** error: (i+3) is not an lvalue

    &strlen( "abcd" ) ; // **** error: strlen( "abcd" ) is not an lvalue
}

http://coliru.stacked-crooked.com/a/c72c5de3b31bbfa2
Assuming that a class is called A, its copying constructor will be declared as:
A(A &)


If that was actually how things were done, we'd never be able to copy objects of type const A. Not to mention the value-category problem. So A(A const&) is more correct.
Last edited on
A (const A&) is NOT the canonical signature for the copy constructor, at least that's what the course I'm reading says. By the way, I'm talking about the C++ institute.
"C++ Institute"... Is that one of those places that take your money in exchange for a worthless piece of paper with your name on it?
Anyway:
http://en.cppreference.com/w/cpp/language/copy_constructor

T::T(const T &) is preferred because it can be passed intermediate values:
1
2
3
4
5
6
7
8
class A{
public:
    A(A &);
};

A f();

A a(f()); // Error. 
Although nowadays you're more likely to define the move constructor. Still, the const reference is preferable because it specifies a contract with the caller that the function will *not* modify the parameter.
1
2
3
4
5
6
7
8
class B{
public:
    B();
    B(B &);
};

B a;
B b(a); // Does this modify a or not? No way to know without looking at the implementation. 


Yes "a" is an L-VALUE, but any L-VALUE is ALSO an R_VALUE.
That's why I said in both cases a non-const reference is being initialized from an rvalue.
There's a human being standing next to a dog. A sign lights up saying "say 'hello' to get fifty dollars". The human says "hello", while the dog just licks its testicles.
What's going on? Aren't they both mammals? Why do they behave differently?

If you want to understand why two things behave differently, you need to look at how they're different, not how they're the same.
@helios

"C++ Institute"... Is that one of those places that take your money in exchange for a worthless piece of paper with your name on it?


Yes, one of those places, with the difference that you're not forced to actually go take the exam.
I just enrolled out of curiosity to see what their idea of a C++ course looks like, because it's not accessible unless you register (for free).
They have 2 levels, Associate and Professional, and the Professional level course can only be accessed after you finish the first level. The first level is for beginners, it's what I'm looking at.

Of course, there are other plenty of other sources to learn...

Well, if it's optionally free then I guess that's alright.
Last edited on
@helios

But here's a question for you:

How's somebody supposed to break into the programming job market without any work experience?
Last edited on
If you have no experience at all, then no "certification" is going to help you. No one in the industry takes those courses seriously. Your time can be better spent on something else, like building a portfolio or contributing to an open source project related to the area you want a job in.
Like I said in a different thread, I'm almost exclusively self-taught and only have a high school diploma. I got my first real job because I had done a bit of reverse engineering in my spare time and that was a key skill for my employer.

But hey, if it does land you a job, great. Just know that you don't have to take any silly courses to find a job. You have options.
1) Other skills/experience useful for a particular job sector. I got my first job off the back of a Chemistry degree with "some FORTRAN experience". That was enough to get me into an interview and programming test for a company that produced molecular modelling software, on the basis that it's easier for someone to pick up the programming skills needed, than it was for someone to learn the science.

2) Build a portfolio of personal projects, and work on open source collaborations. Point to code on GitHub (or whatever the cool kids are using these days) in your CV, so recruiters can see what you can do.

3) Are internships a thing where you are? They can be a way to get your foot in the door.

4) Big corporations can often have entry-level recruitment programs. Again, not much money at first, but a good way to start off.
Last edited on
OK, the only valid option for me where I am is a portfolio.

Internships are BS here, there's no such thing, also "entry-level" positions are off limits if you don't have previous experience (yeah, really!).

I'm self-taught too, no one taught me computers, I learned all by myself by starting to build one from scratch (bare PCB, sockets, components, soldering tool, keyboard assembled the same way, starting up the board and then a lot of fun in assembler).

But where I am, some certification is absolutely required if you come from nowhere otherwise HR scumbags won't even look at you. Hell, you even need diplomas and certifications for stupid data entry positions...
Topic archived. No new replies allowed.
Pages: 12