C++对齐的未来:通过值传递?

Nei*_*l G 18 c++ memory-alignment eigen c++11

阅读Eigen库文档,我注意到某些对象无法通过值传递.C++ 11或计划开发中是否有任何进展可以安全地按价值传递这些对象?

另外,为什么按值返回这些对象没有问题?

Nic*_*las 18

Eigen完全有可能只是一个写得非常糟糕的图书馆(或者只是考虑不周); 只是因为某些东西在线并不能使它成为现实.例如:

按值传递对象在C++中几乎总是一个非常糟糕的主意,因为这意味着无用的副本,而且应该通过引用传递它们.

一般而言,这不是一个好建议,具体取决于对象.有时需要预先C++ 11(因为您可能希望对象不可复制),但在C++ 11中,它永远不是必需的.您可能仍然会这样做,但始终无需通过引用传递值.如果它包含已分配的内存或其他内容,您可以按值移动它.显然,如果它是一种"看起来但不要触摸"的东西,那const&很好.

简单的结构对象,大概就像Eigen一样Vector2d,可能足够便宜(特别是在x86-64,其中指针是64位)复制在性能方面并不多.同时,它开销(理论上),所以如果你在性能关键代码中,它可能会有所帮助.

然后,它可能不会.

Eigen似乎正在讨论的特殊崩溃问题与对象的对齐有关.但是,大多数C++ 03特定于编译器的对齐支持在所有情况下都保证了对齐.所以没有理由"让你的程序崩溃!".我从来没有见过一个基于SSE/AltaVec/etc的库,它使用了特定于编译器的对齐声明,这些声明会导致值参数崩溃.我已经使用了不少.

因此,如果他们遇到某种崩溃问题,那么我会认为Eigen具有......可疑的优点.不是没有进一步调查.

此外,如果一个对象通过值传递是不安全的,正如Eigen文档建议的那样,那么处理这个问题的正确方法就是使对象不可复制.复制分配没问题,因为它需要一个已经存在的对象.然而,Eigen没有这样做,这再次表明开发人员错过了API设计的一些细节.

但是,对于记录,C++ 11具有alignas关键字,这是声明对象应具有特定对齐的标准方式.

另外,为什么按值返回这些对象没有问题?

谁说没有(注意复制问题,而不是对齐问题)?不同之处在于您无法通过引用返回临时值.所以他们没有这样做,因为这是不可能的.

  • 值得注意的是,虽然VC++还不支持`alignas`,但确实有[`__declspec(align(#))`](http://msdn.microsoft.com/en-us/library/83ythb65.aspx),所以语义是可能的,只是还没有可移植的语法. (4认同)
  • @MooingDuck:VS还不支持`alignas`,但如果GCC完全支持16字节对齐(使用特定于编译器的对齐指令),那么它应该通过`alignas`支持16字节对齐.如果编译器*不能*进行16字节对齐,那么...甚至不可能通过*value*安全地创建这些东西. (3认同)
  • @NeilG:我猜测按值返回对象没有问题,因为无论如何都不能使用临时(可能是未对齐或甚至不存在).无论临时在何处(或是否),这些值在返回之前和之后都是正确对齐的. (2认同)

GMa*_*ckG 11

他们可以在C++ 11中做到这一点:

class alignas(16) Matrix4f
{
    // ...
};
Run Code Online (Sandbox Code Playgroud)

现在,类将始终在16字节边界上对齐.

也许,也许我很傻,但这不应该是一个问题.鉴于这样的类:

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];
};
Run Code Online (Sandbox Code Playgroud)

编译器现在有义务分配一个Matrix4f16字节的边界,因为这会破坏它; 班级alignas应该是多余的.但不知怎的,过去我一直都知道错了.

  • @GManNickG:有时,当性能至关重要时(因为它是Eigen所针对的那种代码),并且语言是有限的(就像在C++ 11之前的C++中那样),唯一可接受的选择是做危险的东西,并对它发出重大警告.我不认为这是Eigen的一个错误:这是一个设计决定,在我看来作为一个有效的用户.在C++ 11中添加对齐工具很棒,但它表明了它们之前缺乏的重要性:如果库可以解决这些问题,那么C++ 11就不需要对齐. (4认同)
  • @BenVoigt:啊.:/好吧,至少在`alignas`中,他们需要编译器吐出一个错误,说"对不起,我做不到." (Ergo,在真正需要的时候强制通过引用传递.) (3认同)