2012-04-04 31 views
16

Đọc tài liệu thư viện Eigen, tôi nhận thấy rằng some objects cannot be passed by value. Có bất kỳ sự phát triển nào trong C++ 11 hoặc các dự án phát triển có kế hoạch sẽ làm cho nó an toàn để vượt qua các đối tượng đó theo giá trị không?Tương lai của liên kết C++: truyền theo giá trị?

Ngoài ra, tại sao không có vấn đề với trả lại các đối tượng như vậy theo giá trị?

+6

Bạn đã xem ['std :: aligned_storage <>'] (http://en.cppreference.com/w/cpp/types/aligned_storage) chưa? – ildjarn

+2

Tôi chưa bao giờ nghe nói về một đối tượng không thể được truyền theo giá trị, và sẽ xem xét một đối tượng như vậy được thiết kế kém. Tôi tự hỏi tại sao Eigen lại làm vậy? –

+0

@ildjarn: Bây giờ tôi có :) Bạn có thể giải thích cách nó ảnh hưởng đến việc chuyển một loại theo giá trị? –

Trả lời

9

Họ có thể làm điều này trong C++ 11:

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

Bây giờ lớp sẽ luôn luôn được xếp trên một ranh giới 16-byte.

Ngoài ra, có thể tôi đang ngớ ngẩn nhưng điều này không phải là vấn đề. Cho một lớp như thế này:

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]; 
}; 

Trình biên dịch hiện nay đang buộc phải phân bổ một Matrix4f trên một ranh giới 16-byte dù sao, vì đó sẽ phá vỡ nó; mức lớp học alignas sẽ không cần thiết. Nhưng tôi đã từng được biết là sai trong quá khứ, bằng cách nào đó.

+0

Tất nhiên, sau đó bạn cũng cần các ngăn xếp liên kết 16 byte ... Tôi nghĩ một số trình biên dịch phổ biến không tôn trọng các yêu cầu liên kết cho các biến và đối số cục bộ trừ khi bạn cũng định cấu hình sắp xếp ngăn xếp. –

+3

@BenVoigt: Ah. :/Vâng, ít nhất với 'alignas' họ trình biên dịch là cần thiết để nhổ ra một lỗi nói," xin lỗi, tôi không thể làm điều đó. " – GManNickG

+0

@BenVoigt: Nếu đó là trường hợp, sau đó bạn không bao giờ có thể đặt trình biên dịch nội tại (không có cấu hình trình biên dịch đặc biệt) cho SSE hoặc những thứ khác trên stack, vì chúng cần 16 byte căn chỉnh. –

16

Hoàn toàn có thể là Eigen chỉ là một thư viện được viết khủng khiếp (hoặc chỉ kém suy nghĩ); chỉ vì một cái gì đó là trực tuyến không làm cho nó đúng. Ví dụ:

Chuyển đối tượng theo giá trị hầu như luôn là một ý tưởng rất tồi trong C++, vì điều này có nghĩa là các bản sao vô dụng và chúng sẽ chuyển chúng theo tham chiếu thay thế.

Đây không phải là lời khuyên tốt nói chung, tùy thuộc vào đối tượng. Đôi khi cần thiết trước C++ 11 (vì bạn có thể muốn một đối tượng không thể sao chép được), nhưng trong C++ 11, nó là không bao giờ cần. Bạn vẫn có thể làm điều đó, nhưng không bao giờ cần thiết để luôn chuyển giá trị theo tham chiếu. Bạn chỉ có thể di chuyển nó theo giá trị nếu nó chứa bộ nhớ được cấp phát hoặc cái gì đó. Rõ ràng, nếu đó là một loại "nhìn-nhưng-không-chạm", const& là tốt.

Đối tượng cấu trúc đơn giản, có lẽ là số Vector2d của Eigen có thể đủ rẻ để sao chép (đặc biệt là ở x86-64, trong đó con trỏ là 64 bit) sao chép không có ý nghĩa nhiều về hiệu suất. Đồng thời, nó trên không (theo lý thuyết), vì vậy nếu bạn đang ở trong mã quan trọng hiệu suất, nó có thể giúp đỡ.

Sau đó, một lần nữa, nó có thể không.

Vấn đề tai nạn cụ thể mà Eigen dường như đang nói đến liên quan đến việc căn chỉnh đối tượng. Tuy nhiên, hầu hết sự hỗ trợ liên kết của trình biên dịch C++ 03 đảm bảo rằng sự liên kết trong mọi trường hợp. Vì vậy, không có lý do gì nên "làm cho chương trình của bạn sụp đổ!". Tôi chưa bao giờ thấy một thư viện dựa trên SSE/AltaVec/etc sử dụng các khai báo liên kết cụ thể của trình biên dịch gây ra sự cố với các tham số giá trị. Và tôi đã sử dụng khá nhiều.

Vì vậy, nếu họ đang gặp phải một số vấn đề trục trặc với điều này, thì tôi sẽ xem xét Eigen là ... công đức đáng ngờ. Không phải điều tra thêm.

Ngoài ra, nếu một đối tượng không an toàn để truyền theo giá trị, như các tài liệu Eigen đề xuất, thì cách thích hợp để xử lý điều này sẽ làm cho đối tượng không thể sao chép được. Việc gán bản sao sẽ ổn, vì nó yêu cầu một đối tượng đã tồn tại. Tuy nhiên, Eigen không làm điều này, điều này một lần nữa gợi ý rằng các nhà phát triển đã bỏ lỡ một số điểm thiết kế API tốt hơn.

Tuy nhiên, đối với bản ghi, C++ 11 có từ khóa alignas, đây là cách tiêu chuẩn để khai báo rằng đối tượng phải có một căn chỉnh nhất định.

Ngoài ra, tại sao không có vấn đề với trả lại các đối tượng đó theo giá trị?

Ai nói rằng không có (chú ý vấn đề sao chép, chứ không phải vấn đề căn chỉnh)? Sự khác biệt là bạn không thể trả lại giá trị tạm thời theo tham chiếu. Vì vậy, họ không làm điều đó bởi vì nó không thể.

+0

Cảm ơn câu trả lời của bạn (+1) - Trả lời câu hỏi của bạn "ai nói không?" Tôi chỉ trích dẫn phần cuối của tài liệu được liên kết. Họ nói không có. –

+2

@NeilG: Tôi đoán rằng không có vấn đề gì với việc trả về các đối tượng theo giá trị, vì tạm thời (có thể chưa được ký hoặc thậm chí không tồn tại) không thể được sử dụng.Các giá trị được căn chỉnh đúng cả trước và sau khi trả về, bất kể ở đâu (hoặc nếu) tạm thời. –

+0

@MooingDuck: Cảm ơn, điều đó trả lời phần trả về của câu hỏi của tôi. –

Các vấn đề liên quan