In C++ binaries, I find Qt methods like ??4QString@@QEAAAEAV0@AEBV0@@Z which demangle to

public: class QString & __ptr64 __cdecl QString::operator=(class QString const & __ptr64) __ptr64

or in shorter form, QString& QString::operator=(QString const&). The return value does not appear to be used. What is the purpose of this "unary equals", given that it does not seem to be a construct people write in the original code?


I found the source of my confusion. I'm perfectly award of the calling convention with this, and what operator= is supposed to do. It's common, in my experience, for people to indicate this as a direct argument when reversing software. This is, for instance, what IDA does. It was what I was intending to do as well. So, it would have been considered unary, as I wrote it only take on argument (this).

It turns out that IDA somehow incorrectly assigned the type, and gave it the signature __int64 __fastcall QString__operator_(_QWORD) instead of QString* __fastcall QString__operator_(QString *, QString const *). I don't know what caused this. The output from [demangler.com], which I put in the first half of my post, did not include the implicit this, contrary to my expectations.

  • The return type seems to be a reference, not a pointer. C++ allows you to choose any return type for operator=, including void. But the default behavior is to return *this as a reference.
    – MSalters
    Jun 22 '20 at 12:21
  • It's not unary. The single parameter you see is the second operand, and the first operand is this (it's a class member function, not a free function). Jun 22 '20 at 13:33

It is rather C++ question, but nonetheless:

what you see is an assignment operator for the class QString. It enables you to write things like a = b, where a, b are of QString type.

The reason why it returns value is to enable you to write: a = b = c instead of a = c and b = c and you may see this pattern in case of other operators overloading (see question for instance).

C++ standard demands the compiler to generate the = operator if it wasn't written by a programmer, so you can expect it to be present even if not used directly.


The default assignment operator for primitives returns a value, and the standard convention for operator overloading is to not deviate from the behavior of the operator you are overloading. This is why it's good practice to continue to return the assigned reference from the assignment overload operator.

Because of this behavior, there's a well-used idiom in C (and to C++ by extension) regarding checking the return value of a function upon assignment.

For example, consider an invocation of realloc:

// int *ptr;
// size_t size;

size *= 2;
int *nptr = realloc(ptr, size);
if (nptr)
    ptr = nptr;
    return ERROR;

We can simplify the code by moving assignment expressions inside the if condition. Here, we take advantage of two assignment expressions, size *= 2, which returns the value of the variable after doubling, and the assignment to nptr, which will be NULL (0) on failure.

// int *ptr;
// size_t size;

int *nptr;
if (nptr = realloc(ptr, size *= 2))
    ptr = nptr;
    return ERROR;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.