Adel Boutros
Adel Boutros

Reputation: 10285

What is wrong with this c++ code?

As you can see I am new to C++, but I can't understand why y = new Person() in function foo is wrong. Thanks for your help.

I get the this error:

error: no match for ‘operator=’ in ‘y = (((Person*)operator new(32u)), (, ))’

UPDATE:

I will accept the answer with the most upvotes by tonight or the one that is more convincing.

The argument between me and my friend is wether the function foo can change the object and propagate the change outside the function like when doing y = Person(), then also brother will change or will it remain intact? .

CODE:

#include <iostream>
using namespace std;

 class Person {
   public:  
    int age;
    char name[25];

    Person() {
            age = 0;

    }
};

void foo(Person &y)
{
    y = new Person();
}

int main()
{
    Person *brother = new Person();
    brother->age = 20;

    cout << "age = " << brother->age << endl;
    foo(*brother);
    cout << "age = " << brother->age << endl;
    return 0;
} 

Upvotes: 0

Views: 285

Answers (5)

AnotherProgrammer
AnotherProgrammer

Reputation: 368

Never confuse yourself with the & and * operators when dealing with pointer operations. '&' is used in different context. &, when used in a function's formal parameters is a reference parameter , this operator passes a variable by reference(by its address).However the variable y still acts like a normal variable.
So this block of code..

void foo(Person &y) 
{ 
y = new Person(); 
}

would not work as new Person() is parsing a pointer to a variable. For example,

int * intp = new int;
int variable = intp;

this is the type of thing that's happening here.A reference parameter acts like a variable but actually has direct access to the variable due to the fact that it's a call by referance operation. The correct way to write this function will look like this

 void foo(Person ** y) 
{ 
*y = new Person(); 
}

That is if you're trying to initialize a class pointer via a function. As cooky said this is a misconception people make in c++ whom program in languages that require the new keywork in order to create an object/variable. SOURCES
http://fredosaurus.com/notes-cpp/functions/refparams.html

Upvotes: 2

cooky451
cooky451

Reputation: 3510

You probably come from a language were objects can only be created with new. In C++, this is not the case. And unless you really need it, you should not use new. Just create it as a normal variable:

#include <iostream>
#include <string>

class Person
{
public:
    unsigned age;
    std::string name;
    Person(unsigned age, std::string name)
        : age(age)
        , name(std::move(name)) // move is C++11
    {}
};

int main()
{
    Person brother(8, "Tim John");
    std::cout << "age = " << brother.age << '\n';
    // Edit regarding the question in the comments:
    brother = Person(16, "John Tim");
    std::cout << "age = " << brother.age << '\n';
}

Your problem with the code above is that new returns a Pointer, and you are trying to assign a pointer to a Person, which obviously can't work.

Upvotes: 7

Dialecticus
Dialecticus

Reputation: 16761

In function foo the line should be

y = Person();

y is not a pointer.

EDIT: actually, this is the wrong answer (even though you're currently accepted it from Jon). You are not supposed to mix heap and stack, and cause memory leaks like that. The right way to do it is to change members of the object directly. Assignment operator (operator=) will change the members of the object. Because the question is not about mixing heap and stack, but about changing object here's the code that better explains the problem. Note that there's no new here to complicate the issue.

void foo(Person &y)
{
    y = Person();
}

int main()
{
    Person brother;
    brother.age = 20;

    ...
    foo(brother);
    ...

    return 0;
}

After y = Person() the brother object will be changed because y is brother and assignment operator changes the members of the object.

Upvotes: 2

andrea.marangoni
andrea.marangoni

Reputation: 1499

you are tryng to call the "new" operator on a reference. while the "new" is used only with pointers. pass to void foo( ) function

 Person* 

instead of

Person&

A little explanation :

The right way to pass a parameter depends on what you have to do!!

If you want to do side effects to the object passed to the function the right way is to declare :

void foo(Person& person)

the object person can be modified.. if you don t waant to do side effects to the object you have to declare the object 'const':

void foo(const Person& person)

the const means you cannot modify the object inside your method even if you are passing a reference..

then you can pass a pointer:

void foo(Person* person)

here you can modify the object that "person" is pointing at, but you have a copy of the original pointer.

last way to pass parameters is :

void foo(Person*& person)

here you have an alias of the original pointer. alias means "the same pointer with a different name"

Upvotes: 1

Sebastian Mach
Sebastian Mach

Reputation: 39089

void foo(Person &y)
{
    y = new Person();
}

y is a reference, not a pointer. To reassign to y, you'd use

y = Person();

but if you really want to allocate a new person, you'd use

void foo(Person* &y) // reference to pointer to Person

With a reference, you basically say that you modify the value at the calling site.

Note that your current code leak. If you have a bare pointer that you want to manage yourself, you have to delete it first:

void foo (Person*& y)
{
    delete y;
    y = new Person;
}

But as you see, the code is already becoming messy without knowing your target. It might be more appropriate to delete at the calling site, or to not allocate y at all before calling foo(...).

Also note that using foo (Person* y) instead would not solve the issue of newing at the calling site:

void foo (Person *y) 
{
    y = new Person();
}

This of course compiles, but modifies only foo's own y variable. The caller will have an unchanged pointer.

Note that you'd better use value types or smart pointers, as it is non-trivial to write exception safe code that manually manages memory.

Upvotes: 4

Related Questions