I have the following .h file
class Node
{
private :
int m_data;
Node* m_left;
Node* m_right;
public:
Node(int data) : m_data(data), m_left(nullptr), m_right(nullptr) {}
Node* getLeft() { return m_left; }
Node* getRight() { return m_right; }
int getData() { return m_data; }
};
class Tree
{
private :
Node * m_root;
unsigned int m_size;
void freeNode(Node*);
bool insert(Node**, int );
public:
Tree() : m_size(0) {}
~Tree();
int findMaximumVericalSum();
bool insert(int);
};
The implementation, I get an error - what is wrong and how should I fix it
'&' requires l-value
The address-of operator ( & ) must have an l-value as operand.
bool Tree::insert(Node** root, int data)
{
Node* newNode = new Node(data);
if (*root == nullptr) {
*root = new Node(data);
}
else if (data < (*root)->getLeft()->getData())
{
// error '&' requires l-value
insert(&((*root)->getLeft()), data);
}
else if (data > (*root)->getLeft()->getData())
{
}
}
To my surprise, I wasn't able to find a good duplicate for the question as asked (other issues notwithstanding).
The error you see comes from the following piece of code:
&((*root)->getLeft())
And can be vastly simplified into following very little piece:
int bar();
void foo(int*);
void baz() {
foo(&bar());
}
(also can be seen on https://gcc.godbolt.org/z/PuwtuT)
This produces exactly the same compiler error. And the reason for this is that C++ prohibits taking an address of prvalues, and while whole rvalue/lvalue discussion is super complicated, it is easy to remember that when function returns a value, it is always an prvalue. (If function returns a reference, this is a different story). You can, however, pass an rvalue by either const or rvalue reference.
I can not immediately offer a solution to your problem, because I am not super clear what is your end goal. But I do hope that this answer could at least steer your thoughts and allow you to come up with another question.
Node* getLeft()
This function returns a prvalue.
return m_left;
The prvalue is initialised from this expression. It is not possible to get address of m_left from the prvalue. More generally, it is not possible to get the address of any prvalue. The operand of the addressof operator must be an lvalue.
&((*root)->getLeft()
what is wrong
Here, the operand of the addressof operator is a prvalue. The program is ill-formed.
how should I fix it
Don't try to apply the addressof operator to a prvalue expression.
If your intention is to pass a pointer to (*root)->m_left into the function, then you need some way to access that member.
A solution is to give access to the member by it public, or through friendship.
Another is to provide a public getter that returns a reference, rather than a copy of the member.
A third solution is to add a setter function. In that case, you can use a local variable as argument to the recursion, and then call the setter with the variable after it was modified by the function.
Furthermore, Tree::insert is declared to return bool, but lacks any return statements. Behaviour of the program is undefined (or would be if it was well-formed in the first place).
P.S. Your function doesn't handle the case of data == (*root)->getLeft()->getData().
Related
Here is the code that might help you understand my problem, i am using a node class and a list class. Here is the error:[Error] lvalue required as left operand of assignment. any help would be appreciated..!!
class Node{
private:
int data;
Node* next;
public:
void SetNext(Node* next){
this->next=next;
}
void SetData(int data){
this->data=data;
}
Node* GetNext(){
return next;
}
int GetData(){
return data;
}
};
class List{
private:
Node *CurrentLocation;
public:
List(){
CurrentLocation=NULL;
}
void SortList(){
Node *t1,*t2;
int temp;
for(t1=CurrentLocation;t1!=NULL;t1=t1->GetNext()){
for(t2=CurrentLocation;t2!=NULL;t2=t2->GetNext()){
if(t2->GetData()>t1->GetNext()->GetData()){
temp=t2->GetData();
t2->GetData()=t2->GetNext()->GetData();
t2->GetNext()->GetData()=temp;
}
}
}
}
};
You are trying to assign to an rvalue.
This rvalue is a temporary copy of your data. not the original one. It will be destroyed as soon as the expression executes, hence u can't assign to it.
To assign to your data, u must return a reference to it, as follows
int& GetData(){
return data;
}
As user4581301 has mentioned, I advise you to see this What are rvalues, lvalues, xvalues, glvalues, and prvalues?
The previous description was upon the problem itself but It would be better to write a setter for your data like your getter, as follows
void setData(int newData){
data = newData;
}
Here's the problem line:
t2->GetData()=t2->GetNext()->GetData();
The issue is that the GetData() function returns a copy of the member data which has no local storage (you haven't assigned it to a named variable, hence it's an rvalue). The reason the compiler complains is because really this does nothing. You're assigning a new value to a temporary value that's going away immediately after the line executes.
Converting the member function to
int& GetData(){
return data;
}
means when you call t2->GetData() it actually refers to the data member of t2 and it isn't just a temporary that goes away.
Really though it's probably just better to make data a public member variable so you can just set it/read from it directly
This line is problematic:
t2->GetData()=t2->GetNext()->GetData();
You're trying to assign a value into the data int. However, the GetData member function don't return data itself: is instead returns a temporary copy. You cannot assign into temporaries. To grossly simplify, the compiler call temporaries as rvalue, and non temporary as lvalue. Assignments need lvalues, as it would make little sense to assign into temporaries.
The best would be to use the setter function to set the value:
t2->SetData(t2->GetNext()->GetData());
Here the setter will assign into the data data member.
I have to create a copy constructor for a binary tree with the signature bstt(const bstt& other). I attempted to do so, but I get the following error (in the last code block).
I thought I needed to change my helper function signature to include a const, but I tried a few combinations and none of them worked. How can I fix this?
Helper function:
void _postordercopy(NODE*& thisT, const NODE*& otherT)
{
if(otherT==nullptr){
thisT=nullptr;
}
else
{
NODE* tmp=new NODE;
tmp->Key=otherT->Key;
tmp->Value=otherT->Value;
tmp->Left=otherT->Left;
tmp->Right=otherT->Right;
tmp->isThreaded=otherT->isThreaded;
_postordercopy(thisT->Left,otherT->Left);
_postordercopy(thisT->Right,otherT->Right);
}
}
Copy Constructor:
bstt(const bstt& other)
{
Size=other.Size;
_postordercopy(Root,other.Root);
}
Error Message:
bstt.h:110:35: error: no matching function for call to ‘bstt<int, int>::_postordercopy(bstt<int, int>::NODE*&, bstt<int, int>::NODE* const&)’
You are creating a tmp node in your _postordercopy function, assigning to it, but aren't doing anything with it. Further, you are copying over the exact pointers for Left and Right. That doesn't look right either.
I think this is what you really want for a recursive "copy the tree" function:
NODE* copyTree(const NODE* other)
{
NODE* newTree = nullptr;
if (other!=nullptr)
{
newTree = new NODE;
newTree->Key = other->Key;
newTree->Value = other->Value;
newTree->isThreaded = other->isThreaded;
newTree->Left = copyTree(other->Left);
newTree->Right = copyTree(other->Right);
}
return newTree;
}
And then in your copy constructor, just invoke it as follows:
bstt(const bstt& other)
{
this->Size = other.Size;
this->Root = copyTree(other.Root);
}
I will assume that bstt::Root is declared as NODE*, as this seems most likely.
The second parameter to _postordercopy is of type const NODE*&, a reference to a pointer to a constant NODE. What is the type of the argument you try to pass in? Since other is declared const, each of its members is const. So other.Root is a constant pointer to NODE, also known as NODE* const – the const is tacked on the far right of the declared type. This is incompatible with the parameter type. (See What is the difference between const int*, const int * const, and int const*? for a more thorough discussion of this distinction.)
The problem is that a non-constant reference cannot be initialized from a constant. Since other has to be const, you'd need to change the type of the function parameter to match what you give it. One solution is to move const so that it qualifies the pointer rather than the pointer-to object: NODE* const &. Another solution is to remove the ampersand, as that is a bit wasteful in this case: const NODE*. (The reference adds an extra layer of indirection that provides no benefit.) Think about what your function is supposed to do, and const-qualify whatever is supposed to not change. In this case, the node pointed to by the second parameter should not change.
While that resolves your immediate compiler error, there are other errors to address in your code. In addition, I would consider adding two accessor functions to get the root node. These functions could enforce const in a way that you do not get when accessing Root directly.
NODE *& get_root() { return Root; }
const NODE * const & get_root() const { return Root; }
The main difference is that the type of other.Root is NODE * const, which drops the const-qualifier for the node, whereas other.get_root() would yield a const NODE * const, which propagates the qualifier. At the same time, this->get_root() would yield a simple NODE* since this is not const-qualified. You get to use the same syntax, and the const-ness is propagated appropriately.
Trying to edit a node in a linked list, the "next node" is inside the private section of my node class,
i added a method which only returns the Node* in the public in order to edit it when i need to, and i get an error it's modifiable.
Before i moved the next node pointer to the private section it was inside my public section and worked fined, i don't understand what's the difference between editing the "Node* next" directly or editing "Node* getNext()" which returns exactly the same thing, the Node* next.
Here's some of the relevant code:
class Node;
//Node class
class Node
{
private:
Client* client;
Node* next;
public:
Node();
Node(Client*);
Node(Client*,Node*);
~Node();
Client* getClient();
Node* getNext();
};
//end of Node class
The getters:
Client* MatchmakingAgency::Node::getClient(){
return client;
}
MatchmakingAgency::Node* MatchmakingAgency::Node::getNext(){
return next;
}
and the function that returns the error: (2nd line)
void MatchmakingAgency::addNode(Client* data){
(nodeTail->getNext()) = new Node(data);
nodeTail = nodeTail->getNext();
}
Error message:
Error 1 error C2106: '=' : left operand must be l-value
You are returning a copy of the data member, and, since it is a built-in type, you cannot modify it. If you want to modify a data member via a "getter", you need to return a reference to said member:
Node*& getNext();
It is common practice to privide const overloads for this kind of member function:
const Node*& getNext() const;
Of course, this begs the question: why not use a public data member? There may be good reasons to make the member private, but it is worth thinking about this. If you are not maintaining any invariants, or conforming to some "interface", or don't think you need to provide some non trivial implementation of the access methods, you could use a public data member.
The error is that your getter is returning a COPY of the next ptr. So if you modify the copy of the next pointer like you're doing.
(nodeTail->getNext()) = new Node(data);
You're modifying the wrong thing.
A fix (which is a hack really) to this would be to try changing your getNext to return the actual next reference:
MatchmakingAgency::Node*& MatchmakingAgency::Node::getNext(){
return next;
}
As the link( http://msdn.microsoft.com/en-IN/library/f90831hc.aspx ) at MSDN says:
An lvalue refers to an object that persists beyond a single expression. You can think of an lvalue as an object that has a name. All variables, including nonmodifiable (const) variables, are lvalues.
The call
(nodeTail->getNext()) = new Node(data);
is wrong syntactically as the expression is
(nodeTail->getNext())
is not an lvalue due to your declaration of the function as
Node* getNext();
. In order to make it an lvalue, you would have to make it an lvalue by using the Lvalue Reference Declarator: &, i.e.
define the getter as
Node*& getNext();
To read more about lvalues, see this stackoverflow link:
What are rvalues, lvalues, xvalues, glvalues, and prvalues?
This question already has answers here:
c++ passing by const reference
(4 answers)
Closed 8 years ago.
In my implementation I have a main class Tree which contains many Nodes. Each Node contains a pointer to the next Node, which can be NULL if not implemented. Tree keeps track of the total amount of nodes.
Through the Tree a search function is implemented which returns the Node pointer. However if the Node does not exist yet, a new node is created. This increments the Tree::m_totalnodes variable. However, Tree::GetNode is const, yet this modification does not provide any warnings, errors or runtime failures. What is the reason for this (maybe related that tbNode::m_tree is non-const)?
class Node; //forward declare
class Tree {
public:
Tree() : m_totalnodes(0) {
m_firstnode = new Node(this,0);
}
Node* GetNode(int nodenumber) const { //note const! Should not modify Tree
return m_firstnode->FindNode(nodenumber); //this function eventually modifies it (and no warning)
}
private:
friend class Node;
unsigned int m_totalnodes;
Node* m_firstnode;
};
class Node {
public:
Node(Tree *thetree, int nodenumber) : m_tree(thetree), m_nextnode(NULL), m_nodenumber(nodenumber) {
m_tree->m_totalnodes++;
}
Node* FindNode(int nodenumber) {
if (!m_nextnode)
m_nextnode = new Node(m_tree, nodenumber);
return m_nextnode;
}
private:
Tree* m_tree;
Node* m_nextnode;
unsigned int m_nodenumber;
};
Node* m_firstnode;
When you call a const method like GetNode, this becomes const-qualified to type Tree const *. When you access members like m_totalnodes, they appear to be const-qualified like unsigned int const. You cannot modify the object. m_firstnode becomes Node * const: you cannot modify the pointer, but you can still modify the Node it points to.
If you want to comprehensively avoid accidental modification, access m_firstnode through an overloaded getter function:
Node * & firstnode() { return m_firstnode; }
Node const * firstnode() const { return m_firstnode; }
(Other accessor styles are possible, this is just one example. But note, I don't think it would be safe to return Node const * const & from the second accessor; this may compile but it would return a reference to a temporary.)
Non-const members will call the first method, and will see a modifiable pointer pointing to a modifiable Node. Const-qualified members will call the second, and see neither as modifiable.
That const only promises that the method itself is not going to change the data members. It does not say anything about a Node object not changing data members (which the Node can, since it's a friend).
I am writing a class where multiple instances are linked together like a linked list. Here's a barebones example of the relevant code:
class A
{
public:
void setNext(const A& node) { next = &node; }
const A& getNext() const { return *next; }
private:
const A* next;
}
I have declared the argument to setNext as const because node is not modified by setNext. Class A does not modify the next node either, so the member variable next is declared const. The problem occurs with getNext. Whatever object obtains the next node from the current node may very well need to modify the node, but since the member variable is const the returned reference must be const as well.
From what I've read, const_cast usually indicates a poor design, but it seems like I would have to use it either inside the object that obtains the next node or use it within Class A to return a non-const reference. Is this a valid use of const_cast or is there a flaw in my design somewhere?
And while we're on the subject, is there a preference one way or the other on whether to return a reference or a pointer? I have setNext take a reference to ensure I get a valid instance of A, but the returned value could be returned either way.
I think linked-list private members must be non-const, cause you may want to implement a method which can go across the list an call a specific function on each member, for example. So, your design about a const next member can have a lot of limits. Other thing, you must take care receiving a reference on your setNext : how can you know the end of your list? With a pointer you can set your next as NULL and it'll be the end of the list. But you can keep your member non-const and implement a getNext which return a const object, in this case you'll have :
class A
{
public:
void setNext(A* node) { next = node; }
A& getNext() const { return *next; }
const A& getNext() const { return *next; }
private:
A* next;
}
First, don't reinvent the wheel. If at all possible use boost::intrusive which has already implemented an intrusive list such as this for you, with no additional work needed! You might even be able to get away with std::list or another standard container.
But if you have to:
The pointer to the next variable can't be const because you may need to modify the next node it points to.
setNext will need to take its parameter by non-const reference, because you need to be able to store a non-const item pointer.
Create two overloads of getNext: const A& getNext() const { return *next; } and A& getNext() { return *next; }