19

Reading the Eigen library documentation, I noticed that some objects cannot be passed by value. Are there any developments in C++11 or planned developments that will make it safe to pass such objects by value?

Also, why is there no problem with returning such objects by value?

4

2 回答 2

19

It is entirely possible that Eigen is just a terribly written library (or just poorly-thought out); just because something is online doesn't make it true. For example:

Passing objects by value is almost always a very bad idea in C++, as this means useless copies, and one should pass them by reference instead.

This is not good advice in general, depending on the object. It is sometimes necessary pre-C++11 (because you might want an object to be uncopyable), but in C++11, it is never necessary. You might still do it, but it is never necessary to always pass a value by reference. You can just move it by value if it contains allocated memory or something. Obviously, if it's a "look-but-don't-touch" sort of thing, const& is fine.

Simple struct objects, presumably like Eigen's Vector2d are probably cheap enough to copy (especially in x86-64, where pointers are 64-bits) that the copy won't mean much in terms of performance. At the same time, it is overhead (theoretically), so if you're in performance critical code, it may help.

Then again, it may not.

The particular crash issue that Eigen seems to be talking about has to do with alignment of objects. However, most C++03 compiler-specific alignment support guarantees that alignment in all cases. So there's no reason that should "make your program crash!". I've never seen an SSE/AltaVec/etc-based library that used compiler-specific alignment declarations that caused crashes with value parameters. And I've used quite a few.

So if they're having some kind of crash problem with this, then I would consider Eigen to be of... dubious merit. Not without further investigation.

Also, if an object is unsafe to pass by value, as the Eigen docs suggest, then the proper way to handle this would be to make the object non-copy-constructable. Copy assignment would be fine, since it requires an already existing object. However, Eigen doesn't do this, which again suggests that the developers missed some of the finer points of API design.

However, for the record, C++11 has the alignas keyword, which is a standard way to declare that an object shall be of a certain alignment.

Also, why is there no problem with returning such objects by value?

Who says that there isn't (noting the copying problem, not the alignment problem)? The difference is that you can't return a temporary value by reference. So they're not doing it because it's not possible.

于 2012-04-04T21:22:16.243 回答
11

They could do this in C++11:

class alignas(16) Matrix4f
{
    // ...
};

Now the class will always be aligned on a 16-byte boundary.

Also, maybe I'm being silly but this shouldn't be an issue anyway. Given a class like this:

class Matrix4f
{
public:
    // ...
private:
    // their data type (aligned however they decided in that library):
    aligned_data_type data;

    // or in C++11
    alignas(16) float data[16];
};

Compilers are now obligated to allocate a Matrix4f on a 16-byte boundary anyway, because that would break it; the class-level alignas should be redundant. But I've been known to be wrong in the past, somehow.

于 2012-04-04T21:23:38.477 回答