A pure function is a function that:
- for the same arguments received it always returns the same result;
- running the function has no side effects.
So these are properties of the function. It doesn't matter if the parameter you send to the function is a complex structure or not. If the function respects the above two conditions then it's a pure function. See the linked Wikipedia page for some example of pure and impure behavior.
You asked the question in regards to OOP, so in that context most functions are impure (when bound to an object the function is now called a method) because although they can usually behave in a "pure" manner, they often don't just compute a result based on the received parameters alone, but also change the object they were called on and can access other external data from the system when doing so (like static fields of the class, or other classes).
As for advantages of using pure functions instead of methods that often are written with side effects, the biggest advantage would be that there are less hidden problems. You know exactly what happens to your data when you run a pure function because execution does not depend on any hidden state. So, your code is easier to test. If you have a bug, you simply invoke a function with known parameters and observe the result. Is the result as expected? No? Then the issue is in the function code, and not because somewhere, something external to the function was mutated and it's now involved in the computation of your function, and now you need to look for all places where that thing got mutated, and so on. It basically makes it easier to reason about the data and the behavior because you don't have them both mixed in together in non-visible ways.
There is also a matter of reusing code. In FP code reuse is done with function composition, in OOP is usually done with inheritance. Function composition with no side effects is easier to reason about than relying on (usually) deep hierarchies of tightly coupled classes, with each subclass having the potential of overriding the things inherited from its ancestors.
The topic is very large, but a blunt simplification would be that, with FP you have a more stateless, immutable approach to things, that is easier to reason about and troubleshoot, than having a stateful, mutable programming model like in OOP. A simplistic visual difference would be something like the following.
For OOP, your state grows as methods operate on the data, and you don't really know at a glance who did what, something like this: 
With FP, things are a bit more clean, something like this:

Of course, pure functional programming dealing with no state mutations or side effects would be mostly useless or resume itself to mathematical problems only, so there are ways to have side effects in FP, but it's usually a thing confined at the edge of your system and you have to deal with it explicitly (i.e it's not hidden).