Làm cách nào để chuyển sang C ++ 11?


35

Tôi đã lập trình trong C ++ được một thời gian rồi, nhưng chủ yếu là những thứ xoay quanh các tính năng cấp thấp của C ++. Điều đó có nghĩa là tôi chủ yếu làm việc với các con trỏ và mảng thô. Tôi nghĩ rằng hành vi này được gọi là sử dụng C ++ như C với các lớp. Mặc dù vậy, tôi chỉ mới thử C gần đây lần đầu tiên. Tôi đã ngạc nhiên khi các ngôn ngữ như C # và Java che giấu các chi tiết này trong các lớp thư viện tiêu chuẩn thuận tiện như Từ điển và Danh sách.

Tôi biết rằng thư viện chuẩn C ++ có nhiều thùng chứa như vectơ, bản đồ và chuỗi và C ++ 11 chỉ thêm vào điều này bằng cách có các vòng lặp std :: mảng và ranged.

Làm thế nào để tôi học tốt nhất để sử dụng các tính năng ngôn ngữ hiện đại này và phù hợp với thời điểm nào? Có đúng là công nghệ phần mềm trong C ++ ngày nay hầu như không có quản lý bộ nhớ thủ công?

Cuối cùng, tôi nên sử dụng trình biên dịch nào để tận dụng tối đa tiêu chuẩn mới? Visual Studio có các công cụ sửa lỗi tuyệt vời, nhưng ngay cả VS2012 dường như cũng hỗ trợ C ++ 11 khủng khiếp.


2
Tôi muốn gọi việc hỗ trợ C ++ 11 của VS2012 là "khủng khiếp" là hơi cường điệu, nhưng chắc chắn có thể tốt hơn (thiếu danh sách trình khởi tạo đặc biệt khó chịu đối với mã thử nghiệm / mã đồ chơi). Nhưng lưu ý rằng họ đã thông báo rằng họ sẽ cập nhật trình biên dịch độc lập với phần còn lại của VS, vì vậy tôi đoán chúng ta có thể hy vọng có khá nhiều tính năng C ++ 11 trong VS2012 trong năm 2013.
Martin Ba

3
Lúc đầu, tôi nghĩ việc gợi ý nó cho việc học C ++ 11 sẽ là kỳ quặc, nhưng thấy rằng bạn vẫn bị mắc kẹt trong vùng đất C-With-Classes ... Một thập kỷ trước tôi đã đọc Gia tốc C ++ của Koenig / Moo . Vào thời điểm tôi thực sự đã thực hiện lập trình meta mẫu (tôi chỉ đọc nó để xem xét), nhưng nó vẫn cảm thấy như một sự mặc khải. (Tôi đã sử dụng nó như một cơ sở để giảng dạy C ++ kể từ đó.) Đến từ C With Classes , cuốn sách có thể cho bạn thấy một ngôn ngữ hoàn toàn mới mà bạn không biết bạn có theo ý của bạn. Chỉ có 250 trang và sau đó bạn có thể nhanh chóng chuyển sang một thứ cụ thể C ++ 11, nhưng IMO là một bước đáng giá.
sbi

4
g++ -std=c++11
dòng chảy

Câu trả lời:


50

Đầu tiên, một số quy tắc của ngón tay cái:

  • Sử dụng std::unique_ptrnhư một con trỏ thông minh không có phí. Bạn không cần phải bận tâm với con trỏ thô thường xuyên. std::shared_ptrtương tự như vậy là không cần thiết trong hầu hết các trường hợp. Mong muốn sở hữu chung thường phản bội sự thiếu suy nghĩ về quyền sở hữu ngay từ đầu.

  • Sử dụng std::arraycho các mảng có độ dài tĩnh và std::vectorcho động.

  • Sử dụng rộng rãi các thuật toán chung, đặc biệt:

    • <algorithm>
    • <numeric>
    • <iterator>
    • <functional>
  • Sử dụng autodecltype()bất cứ nơi nào họ có lợi cho khả năng đọc. Cụ thể, khi bạn muốn khai báo một thứ, nhưng thuộc loại mà bạn không quan tâm, chẳng hạn như kiểu lặp hoặc kiểu mẫu phức tạp, hãy sử dụng auto. Khi bạn muốn khai báo một điều theo kiểu của một điều khác, hãy sử dụng decltype().

  • Làm cho mọi thứ an toàn khi bạn có thể. Khi bạn có các xác nhận thực thi bất biến đối với một loại điều cụ thể, logic đó có thể được tập trung trong một loại. Và điều này không nhất thiết phải làm cho bất kỳ chi phí thời gian chạy. Cũng không nên nói rằng (T)xnên tránh các phôi kiểu C ( ) để ủng hộ các phôi kiểu C ++ rõ ràng hơn (và có thể tìm kiếm!) (Ví dụ static_cast:).

  • Cuối cùng, biết quy tắc của ba:

    • Phá hủy
    • Sao chép hàm tạo
    • Toán tử chuyển nhượng

    Đã trở thành quy tắc của năm với việc bổ sung hàm tạo di chuyển và toán tử gán di chuyển. Và hiểu các tài liệu tham khảo rvalue nói chung và làm thế nào để tránh sao chép.

C ++ là một ngôn ngữ phức tạp, vì vậy thật khó để mô tả cách tốt nhất để sử dụng tất cả ngôn ngữ đó. Nhưng thực tiễn phát triển C ++ tốt không thay đổi căn bản với C ++ 11. Bạn vẫn nên ưu tiên các bộ chứa được quản lý bộ nhớ hơn quản lý bộ nhớ thủ công Con trỏ thông minh giúp dễ dàng thực hiện việc này một cách hiệu quả.

Tôi có thể nói rằng C ++ hiện đại thực sự hầu như không có quản lý bộ nhớ thủ công. Ưu điểm của mô hình bộ nhớ của C ++ là nó mang tính quyết định , không phải là thủ công. Các thỏa thuận có thể dự đoán sẽ làm cho hiệu suất dễ dự đoán hơn.

Đối với một trình biên dịch, G ++ và Clang đều cạnh tranh về các tính năng của C ++ 11 và nhanh chóng bắt kịp những thiếu sót của chúng. Tôi không sử dụng Visual Studio, vì vậy tôi không thể nói hay chống lại nó.

Cuối cùng, một lưu ý về std::for_each: tránh nó nói chung.

transform, accumulateerase- remove_iflà tốt cũ chức năng map, foldfilter. Nhưng for_eachnói chung chung hơn, và do đó, ít ý nghĩa hơn, nó không thể hiện bất kỳ ý định nào ngoài việc lặp lại. Bên cạnh đó, nó được sử dụng trong các tình huống tương tự như dựa trên phạm vi forvà nặng hơn về mặt cú pháp, ngay cả khi được sử dụng không có điểm. Xem xét:

for (const auto i : container)
    std::cout << i << '\n';

std::for_each(container.begin(), container.end(), [](int i) {
    std::cout << i << '\n';
});

for (const auto i : container)
    frobnicate(i);

std::for_each(container.begin(), container.end(), frobnicate);

6
Có một số nguyên tắc ràng buộc với các quy tắc này? Nó có vẻ như là một danh sách gợi ý hay, nhưng ... Là một người ngoài cuộc đến với câu hỏi này thông qua Google, làm thế nào câu trả lời của bạn giúp tôi nhận C ++ 11 theo cách có nguyên tắc và sử dụng nó mà không quấn quanh trục C ++ ?
Robert Harvey

3
+1 cho danh sách, nhưng tôi có một nitpick nhỏ: khi (đúng) cảnh báo chống lại std::for_eachtôi sẽ mong đợi phạm vi dựa trên vòng lặp là một sự thay thế tốt hơn so với đơn giản for.
Fabio Fracassi

@FabioFracassi: Rất tiếc. Tôi đã viết đơn giản để tương phản với std::for_each, không phải dựa trên phạm vi . Tôi đã gỡ bỏ nó để tránh nhầm lẫn.
Jon Purdy

1
Tôi sẽ cập nhật nếu không std::for_each(). Khi bạn có lambda, nó chắc chắn tốt hơn một forvòng lặp truyền thống . Với một forvòng lặp dựa trên phạm vi có thể không phải là trường hợp, nhưng bạn đã không viết " forvòng lặp dựa trên phạm vi ".
sbi

@sbi: Trong suy nghĩ của tôi, thuật ngữ forvòng lặp NX bao gồm các forvòng lặp dựa trên phạm vi của Google . Tôi đã chỉnh sửa với nhiều lời giải thích và một ví dụ để làm rõ, cảm ơn bạn.
Jon Purdy

12

Là một điểm khởi đầu:

  • Ngừng sử dụng char*cho chuỗi. Sử dụng std::stringhoặc std::wstringvà chỉ xem mã của bạn ngắn hơn, dễ đọc hơn và an toàn hơn
  • Dừng sử dụng mảng kiểu C (những thứ được khai báo [ ]) và sử dụng std::vectorhoặc một số lớp container thích hợp khác. Những điều tốt đẹp std::vectorlà nó biết chiều dài của chính nó, nó dọn sạch nội dung của nó khi đi ra khỏi phạm vi, nó dễ dàng lặp đi lặp lại, và nó làm cho nó lớn hơn khi bạn thêm nhiều vật phẩm. Nhưng có những bộ sưu tập khác có thể hoạt động tốt hơn cho hoàn cảnh của bạn.
  • Sử dụng std::unique_ptr- và học std::movegần như ngay lập tức. Do đây có thể dẫn đến một số đối tượng noncopyable, lười biếng đôi khi có thể gửi cho bạn hướng std::shared_ptr- và bạn có thể có một số trường hợp sử dụng chính hãng cho std::shared_ptrcũng
  • Sử dụng autokhi khai báo các trình lặp và các loại phụ thuộc vào các khai báo trước đó (ví dụ: trước đó bạn đã khai báo một vectơ của một cái gì đó, bây giờ bạn đang khai báo một cái gì đó, sử dụng auto)
  • Sử dụng các thuật toán và for_eachtrên "thô cho" bất cứ khi nào bạn có thể vì nó không cho người khác đọc vòng lặp của bạn một cách cẩn thận để kết luận rằng trên thực tế bạn đang lặp lại toàn bộ bộ sưu tập, v.v ... Nếu trình biên dịch của bạn hỗ trợ "phạm vi cho" thì hãy sử dụng nó for_each. Tìm hiểu cuộc gọi thuật toán tầm thường như iota, generate, accumulate, find_ifvà vân vân.
  • Sử dụng lambdas - chúng là cách dễ dàng để tận dụng các thuật toán. Họ cũng mở cửa cho nhiều hơn nữa.

Đừng quá bận tâm về việc sử dụng trình biên dịch nào. Sự thiếu hỗ trợ C ++ 11 "khủng khiếp, khủng khiếp" trong VS2012 là không có các mẫu biến đổi (vâng đúng rồi, bạn chỉ sắp sử dụng các mẫu matrixdic) và trình {}khởi tạo không có ở đó. Tôi cũng muốn điều đó nhưng tôi hầu như sẽ không ngừng sử dụng một công cụ phát triển hữu ích đối với nó.

Điều thứ hai cần làm, sau khi ôm hôn std::, là bắt đầu nghĩ RAII. Bất cứ lúc nào bạn có

  • bắt đầu hành động
  • một loạt các hành động với một cái gì đó bạn có được từ việc bắt đầu hành động
  • hành động dọn dẹp cần phải xảy ra ngay cả trong trường hợp ngoại lệ

Sau đó, những gì bạn có là một hàm tạo, một số hàm thành viên và hàm hủy. Viết một lớp học chăm sóc điều đó cho bạn. Bạn thậm chí có thể không phải viết ctor và dtor. Đặt mộtshared_ptr biến thành viên của một lớp là một ví dụ về RAII - bạn không viết mã quản lý bộ nhớ, nhưng khi cá thể của bạn vượt quá phạm vi, điều đúng sẽ xảy ra. Mở rộng suy nghĩ đó để bao gồm những thứ như đóng tệp, giải phóng tay cầm, khóa vv và mã sẽ trở nên đơn giản và nhỏ hơn (trong khi loại bỏ rò rỉ) trước mắt bạn.

Nếu bạn đang cảm thấy thực sự tự tin, thanh trừng printfủng hộ cout, thoát khỏi macro ( #definecông cụ), và bắt đầu tìm hiểu một số "thành ngữ tiên tiến" như pImpl. Tôi có toàn bộ khóa học về vấn đề này tại Pluralsight mà bạn có thể xem bằng cách sử dụng bản dùng thử miễn phí của họ.


2
Tôi thích cách bạn mỉa mai về việc anh ấy không sử dụng các mẫu biến đổi bất cứ lúc nào sớm, nhưng tôi nghĩ thiếu khởi tạo đồng phục là thiếu một cái gì đó thực sự quan trọng cho lập trình hàng ngày.
sbi

Không thể đợi danh sách trình khởi tạo ... chờ đợi để biết khi nào chúng tôi sẽ nhận được chúng ...
Kate Gregory

Một thiếu quan trọng khác trong VS2012 là "tham chiếu giá trị v3", tức là hàm tạo di chuyển được tạo tự động và gán di chuyển.
Mr.C64

3

Làm thế nào để tôi học tốt nhất để sử dụng các tính năng ngôn ngữ hiện đại này và phù hợp với thời điểm nào?

Bằng lập trình. Kinh nghiệm là cách tốt nhất để học hỏi.

C ++ 11 có rất nhiều tính năng mới (tự động, giá trị, con trỏ thông minh mới - chỉ để một vài tên). Bắt đầu tốt nhất là chỉ bắt đầu sử dụng chúng, và đọc về chúng bất cứ khi nào bạn có thể, và bất cứ khi nào bạn tìm thấy một bài viết thú vị.

Có đúng là công nghệ phần mềm trong C ++ ngày nay hầu như không có quản lý bộ nhớ thủ công?

Điều đó phụ thuộc vào những gì bạn cần làm. Hầu hết các ứng dụng có thể thoát khỏi các con trỏ thông minh và quên đi việc quản lý bộ nhớ. Vẫn có những ứng dụng không thể thoát ra dễ dàng như vậy (ví dụ nếu chúng cần vị trí mới hoặc bộ cấp phát bộ nhớ tùy chỉnh vì bất kỳ lý do gì).

Nếu bạn cần sử dụng Qt, bạn sẽ phải sử dụng các quy tắc của họ để quản lý bộ nhớ.

Tôi nên sử dụng trình biên dịch nào để tận dụng tối đa tiêu chuẩn mới?

Bất cứ thứ gì bạn có trong tay đều hỗ trợ tiêu chuẩn mới nhất:

nhưng không có trình biên dịch hỗ trợ tất cả các tính năng.


-7

Trường đại học của tôi vẫn đang sử dụng C ++ cho giảng dạy. Tôi đã lập trình với C ++ được 5 năm và bây giờ tôi là một sinh viên tốt nghiệp. Tất nhiên, bây giờ tôi đang sử dụng rất nhiều Java, Ruby, v.v. Tôi thực sự khuyên bạn đừng quá vội vàng về các tính năng đó trong ngôn ngữ như Java. Theo kinh nghiệm và ý kiến ​​của tôi, sau các tính năng cấp thấp của C ++. Bạn nên xem xét các chủ đề như lập trình chung với C / C ++ như tạo lớp mẫu, hàm mẫu, ghi đè toán tử, phương thức ảo, con trỏ thông minh. Đối với Phần Thiết kế hướng đối tượng, có rất nhiều tính năng mà C ++ có và Java thì không, giống như đa kế thừa. Kế thừa là mạnh mẽ nhưng nguy hiểm quá. Mức độ thực hiện của thiết kế hướng đối tượng trong C ++ cũng là một chủ đề tốt. Giao tiếp giữa các quá trình, các luồng, cũng quan trọng trong C ++.

Đối với trình biên dịch và trình gỡ lỗi. Tôi biết phòng thu hình ảnh là tuyệt vời. Nhưng tôi thực sự khuyên bạn nên học GDB, Valgrind và Make still và giỏi những công cụ này. Microsoft thật tuyệt vời, nhưng nó đã làm quá nhiều thứ cho bạn. Là một sinh viên, bạn thực sự cần phải học những điều mà Microsoft đã làm quá bạn. Đối với trình biên dịch, G ++ là tốt từ GNU.

Rốt cuộc, sau bao nhiêu năm, tôi thực sự cảm thấy, điều quan trọng nhất là các tính năng cấp thấp như mảng thô. Vector thực sự chỉ là một mảng động. Đây là những khuyến nghị của tôi, một cái gì đó có thể quá chủ quan, chỉ cần lấy những gì bạn nghĩ là đúng.


6
Làm thế nào để trả lời câu hỏi này? Câu hỏi không phải là về việc học C ++ nói chung, mà là chuyển sang C ++ 11.
Roc Martí
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.