My program is not compiling and keeps outputing the same error "non-lvalue in assignment." I've tried looking around the internet to why this is happening but I can't seem to find anything. I would really appreciate some input.
#include <iostream>
using namespace std;
class Class
{
public:
Class()
{
Var=0;
}
private:
int Var;
friend void Friend(Class &object);
};
void Friend(Class &object)
{
&object.Var=99;
cout << &object.Var << endl;
}
int main()
{
Class testobject;
Friend(testobject);
}
You won't need the & inside the function
The problem is this line &object.Var=99; You taking the address of object and than accessing .Var, this cant work.
Seems you missunderstood references, you dont have to dereference them (unlike pointer).
Change your function to this:
void Friend(Class &object)
{
object.Var=99;
cout << object.Var << endl;
}
Change the function definition to
void Friend(Class &object)
{
object.Var=99;
cout << object.Var << endl;
}
The reason of the error is described in the following quote of the C++ Standard
if the type of the expression is T, the result has type “pointer to T”
and is a prvalue
Replace &object.Var=99; with object.Var=99; and cout << &object.Var << endl; with cout << object.Var << endl;
When passing an argument, & denotes that you receive the variable as a reference.
void Friend(Class &object) means you get the reference of testobject in object.
&object.Var implies address of object.Var. You cannot assign to that. Hence the error non-lvalue in assignment.
Related
I don't know there is std::addressof available in c++ standard library until today I read some blog. In my understanding, if opeartor & is overloaded, then std::addressof should be used, otherwise it's not necessary to use std::addressof, it should be equivalent with &.
However, just trying to use std::addressof, to validate if it is the same as &, I meet compile error: "call to deleted function 'addressof' ". Don't know why.
Here's the minimal code to demonstrate this problem:
#include <iostream>
#include <memory>
class Foo
{
public:
Foo(int _len): len(_len) {
if(len>0) {
data = new double[len];
}
// compile error: call to deleted function 'addressof'
std::cout << "Foo() " << std::addressof(this) << "/" << std::addressof(data) << std::endl;
}
~Foo() {
// compile ok
std::cout << "~Foo() " << (void*)this << "/" << (void*)data << std::endl;
// compile error: call to deleted function 'addressof'
std::cout << "~Foo() " << std::addressof(this) << "/" << std::addressof(data) << std::endl;
if (data!=nullptr) {
delete[] data;
}
}
private:
int len;
double* data;
};
int main() {
Foo(42);
return 0;
}
C++ standard:
§9.3.2 The this pointer
the keyword this is a prvalue expression
std::addressof
template <class T>
const T* addressof(const T&&) = delete;
So addressof overload for rvalues is deleted. The reason is because you cannot take the address of a prvalue so addressof is modeled to respect that.
That's why you get the error.
Please note that addressof(this) and (void*) this are not even in the same ballpark. The equivalent of addressof(this) would be &this which also doesn't compile.
Suppose I have a class
class Test{
public:
int x;
Test(const Test& obj){x=obj.x;}
};
Why does
Test object_name(Test random_name);
run and does not need another object as a parameter?.
.Something like Test random_name(Test another_random(...)), making it a never ending way of declaring the object?
This line:
Test object_name(Test random_name);
declares a function called object_name that takes a Test as a paramter and returns a Test. It does not declare an object. It is perfectly legal to declare a function like this inside another function, it's just implicitly extern.
Substitute Test with a PoD like int and you will see what is happening
Test object_name(Test random_name); //1
int object_name(int random_name); //2
You can see that the second statement is a function declaration which takes an int as argument and returns an int.
This is due to a well-known rule in CPP related to ambiguity resolution.
From the CPP working draft (N4713):
9.8 Ambiguity resolution [stmt.ambig]
1 There is an ambiguity in the grammar involving expression-statements and declarations: An expression-statement with a function-style explicit type conversion as its leftmost subexpression can be indistinguishable from a declaration where the first declarator starts with a (. In those cases the statement is a declaration.
2 [ Note: If the statement cannot syntactically be a declaration, there is no ambiguity, so this rule does not apply. The whole statement might need to be examined to determine whether this is the case.
Here's a refactored version that should help explain what's going on. I've added another constructor to illustrate what's going on.
#include <iostream>
using namespace std;
class Test{
public:
int x = 27;
Test(const int y) : x(y) { cout << "ctor-1" << endl; }
~Test() {}
Test(const Test& obj) : x(obj.x) { cout << "ctor-2" << endl; }
operator int() const { return x; }
};
int main()
{
cout << "Creating function declaration" << endl;
Test object_name(Test random_name);
// This works fine
cout << "Creating alpha" << endl;
Test alpha(4);
cout << "Calling `object_name`" << endl;
cout << object_name(alpha) << endl;
// This fails because object_name is a function.
// cout << object_name.x << endl;
return 0;
}
Test object_name(Test random_name)
{
cout << "Creating another Test within `object_name`." << endl;
return Test(random_name.x + 13);
}
Here, we see that the first constructor is invoked twice: once for alpha and again within object_name. The second constructor is invoked when we call object_name, which accepts a parameter passed by value.
Output
Creating function declaration
Creating alpha
ctor-1
Calling `object_name`
ctor-2
Creating another Test within `object_name`.
ctor-1
17
I have learned that function name equals function address
like this:
void func(){}
void main() { cout << func; }
But when I used the same code to print memeber function, it went wrong.
class Test{
public:
void func() {}
void printFunc1() {
cout << func << endl;
}
void printFunc2() {
void (Test::*ptrtofn)() = &Test::func;
cout << (void*&)ptrtofn << endl;
}
};
printFunction2() work but printFunction1() doesnt
What makes the difference?
Member function's name is not member function's address?
Is there any reason?
member function != standalone function
Only standalone functions can be converted to pointer implicitely.
4.3 Function-to-pointer conversion [conv.func]
1 An lvalue of function type T can be converted to a prvalue of type “pointer to T.” The result is a pointer to the function. 58
58) This conversion never applies to non-static member functions
because an lvalue that refers to a non-static member function cannot
be obtained.
Please understand "func" is the member function of the class . accessing it directly is itself a compilation error .Rather you should try to use pointer to member function as you have done in printFunction2:
Else if func is function outside the class scope .Then it can be done as below :
#include <iostream>
using namespace std;
void func() {cout<<"\n calling func\n";}
void printFunc1() {
cout << endl<<hex<<(void*)func << endl;
}
int main() {
printFunc1();
return 0;
}
I know that the this pointer is implicitly passed to member functions when they are called. When I try to get the address of this pointer (via &this), though, I get the compiler error "lvalue required". Why is this?
class st
{
int a,b;
public :
void print()
{
cout << &this; //gives lvalue required... why?
cout << this; //will print address of object.
}
}
this is not an lvalue but an prvalue. From [class.this]:
In the body of a non-static (9.3) member function, the keyword this is a prvalue expression whose value is the address of the object for which the function is called. The type of this in a member function of a class X is X*. If the member function is declared const, the type of this is const X*, if the member function is declared volatile, the type of this is volatile X*, and if the member function is declared const volatile, the type of this is const volatile X*.
Emphasis mine
& requires an lvalue so you cannot get the address of this.
Because this pointer is a rvalue. this pointer is a constant value, it is passed to the member function like a local variable, so it's value is stored in a memory location that would become invalid when returning from that function.
Presumably you're trying to print out the values in the object. cout doesn't know how to do this, and you have to teach it.
cout << *this;
might do this if cout knew how to do it, but you can teach it. Here's an example that is more natural c++. (You should also consider a constructor).
#include <iostream>
using namespace std;
class st
{
public:
int a,b;
};
std::ostream& operator<<(std::ostream& s, const st& val)
{
return s << "a:" << val.a << " b:" << val.b ;
}
int main() {
st foo;
foo.a = 1;
foo.b = 2;
cout << "foo is " << foo << endl;
}
In the following code, I'm not able to pass a temporary object as argument to the printAge function:
struct Person {
int age;
Person(int _age): age(_age) {}
};
void printAge(Person &person) {
cout << "Age: " << person.age << endl;
}
int main () {
Person p(50);
printAge(Person(50)); // fails!
printAge(p);
return 0;
}
The error I get is:
error: invalid initialization of non-const reference of type ‘Person&’ from an rvalue of type ‘Person’
I realize that this is something to do with passing an lValue to a function expecting a rValue... Is there a way to convert my lValue to rValue by using std::move or something? I tried taking a constant parameter, but that does not seem to work.
Simply make your print function take your argument by const&. This is also logically right as it doesn't modify your argument.
void printAge(const Person &person) {
cout << "Age: " << person.age << endl;
}
The actual problem is the other way around. You are passing a temporary(rvalue) to a function which expects an lvalue.
Or, if you have a C++11-compliant compiler, can use the so called universal reference approach, which, via reference collapsing rules, can bind to both lvalue and rvalue references:
#include <iostream>
using namespace std;
struct Person {
int age;
Person(int _age): age(_age) {}
};
template<typename T> // can bind to both lvalue AND rvalue references
void printAge(T&& person) {
cout << "Age: " << person.age << endl;
}
int main () {
Person p(50);
printAge(Person(50)); // works now
printAge(p);
return 0;
}
Or, in C++14,
void printAge(auto&& person) {
cout << "Age: " << person.age << endl;
}
Your code doesn't work if you run g++ or gcc compilers. You need to add const to void printAge(const Person &person). However, in Visual Studio it will work fine. I've tested for VS2010 and VS2012 and in both the following code works fine.
#include<iostream>
using namespace std;
struct Person {
int age;
Person(int _age): age(_age) {}
};
void printAge(Person &person) {
cout << "Age: " << person.age << endl;
}
int main () {
Person p(50);
printAge(Person(50)); // DOES NOT fail!
printAge(p);
return 0;
}