Repository navigation
Expand file tree
/
Copy pathdb.json
More file actions
1 lines (1 loc) · 440 KB
/
Copy pathdb.json
File metadata and controls
1 lines (1 loc) · 440 KB
1
{"meta":{"version":1,"warehouse":"5.0.1"},"models":{"Asset":[{"_id":"themes/butterfly/source/css/index.styl","path":"css/index.styl","modified":1,"renderable":1},{"_id":"themes/butterfly/source/css/var.styl","path":"css/var.styl","modified":1,"renderable":1},{"_id":"themes/butterfly/source/css/background.css","path":"css/background.css","modified":1,"renderable":1},{"_id":"themes/butterfly/source/js/main.js","path":"js/main.js","modified":1,"renderable":1},{"_id":"themes/butterfly/source/js/tw_cn.js","path":"js/tw_cn.js","modified":1,"renderable":1},{"_id":"themes/butterfly/source/js/utils.js","path":"js/utils.js","modified":1,"renderable":1},{"_id":"themes/butterfly/source/img/404.jpg","path":"img/404.jpg","modified":1,"renderable":1},{"_id":"themes/butterfly/source/img/butterfly-icon.png","path":"img/butterfly-icon.png","modified":1,"renderable":1},{"_id":"themes/butterfly/source/img/error-page.png","path":"img/error-page.png","modified":1,"renderable":1},{"_id":"themes/butterfly/source/img/favicon.ico","path":"img/favicon.ico","modified":1,"renderable":1},{"_id":"themes/butterfly/source/img/friend_404.gif","path":"img/friend_404.gif","modified":1,"renderable":1},{"_id":"themes/butterfly/source/img/assetsbg-pattern.jpg","path":"img/assetsbg-pattern.jpg","modified":1,"renderable":1},{"_id":"themes/butterfly/source/js/search/algolia.js","path":"js/search/algolia.js","modified":1,"renderable":1},{"_id":"themes/butterfly/source/js/search/local-search.js","path":"js/search/local-search.js","modified":1,"renderable":1},{"_id":"source/CNAME","path":"CNAME","modified":1,"renderable":0},{"_id":"source/image/A4.jpg","path":"image/A4.jpg","modified":1,"renderable":0},{"_id":"source/image/assetsavatar.jpg","path":"image/assetsavatar.jpg","modified":1,"renderable":0},{"_id":"source/image/assetsbackground.jpg","path":"image/assetsbackground.jpg","modified":1,"renderable":0},{"_id":"source/image/壁纸1.jpg","path":"image/壁纸1.jpg","modified":1,"renderable":0},{"_id":"source/image/山田凉.jpg","path":"image/山田凉.jpg","modified":1,"renderable":0},{"_id":"source/image/带宽_爱给网_aigei_com.png","path":"image/带宽_爱给网_aigei_com.png","modified":1,"renderable":0},{"_id":"source/image/微信图片_20250227225808.jpg","path":"image/微信图片_20250227225808.jpg","modified":1,"renderable":0},{"_id":"source/image/微信图片_20250227225819.jpg","path":"image/微信图片_20250227225819.jpg","modified":1,"renderable":0},{"_id":"source/image/微信图片_20250227225830.jpg","path":"image/微信图片_20250227225830.jpg","modified":1,"renderable":0},{"_id":"source/image/微信图片_20250410145107.jpg","path":"image/微信图片_20250410145107.jpg","modified":1,"renderable":0},{"_id":"source/image/微信图片_20250227225824.jpg","path":"image/微信图片_20250227225824.jpg","modified":1,"renderable":0},{"_id":"source/image/微信图片_20250311204951.jpg","path":"image/微信图片_20250311204951.jpg","modified":1,"renderable":0},{"_id":"source/image/微信图片_20250410145115.png","path":"image/微信图片_20250410145115.png","modified":1,"renderable":0},{"_id":"source/image/阿尼亚.jpg","path":"image/阿尼亚.jpg","modified":1,"renderable":0},{"_id":"source/music/M800001LjzC74ccFMh.mp3","path":"music/M800001LjzC74ccFMh.mp3","modified":1,"renderable":0}],"Cache":[{"_id":"source/CNAME","hash":"c6a054ecc02b58fbde31263ca6f8e6b1a6465b43","modified":1768899225879},{"_id":"source/_data/link.yml","hash":"31e987eeae6bd675ac499ed676b91c3591ad4b57","modified":1741102829906},{"_id":"source/image/带宽_爱给网_aigei_com.png","hash":"aa72c854a315e5650471723aa12f9d9d9dab6288","modified":1740667907760},{"_id":"source/_posts/first-blog.md","hash":"2ea9d8f1b901bae2dec538c9bfc3197c12b6bc0e","modified":1741175971930},{"_id":"source/comments/index.md","hash":"71cb494df609a3fa4f06c1bf28e99fdb3ad3fce1","modified":1741359765273},{"_id":"source/_posts/eigth-blog.md","hash":"94c135a3c756ab30d851950d522c3d869d504a99","modified":1744269192830},{"_id":"source/_posts/ninth-blog.md","hash":"5b51b4b2062c6646a9ef82fb36214a0bbf316cf9","modified":1746687905729},{"_id":"source/_posts/fith-blog.md","hash":"9284f2d459c610ebab901d1a39a0309d6e71f651","modified":1743235288161},{"_id":"source/_posts/hello-world.md","hash":"c1c7b481f08dd46260209356ef22e24a51f8bb53","modified":1741158313032},{"_id":"source/_posts/forth-blog.md","hash":"dfeae51cf28f39a822d7e3803471247f68d44cdc","modified":1741853039890},{"_id":"source/_posts/C++1.md","hash":"8ee81a900739911eea5302487c0fd6ede641daf6","modified":1750146539757},{"_id":"source/_posts/second-blog.md","hash":"4c55838e8e69d9884aa42f70b978d4135ea56eaa","modified":1741181074401},{"_id":"source/_posts/siventh-bolg.md","hash":"cdad2fff702f82e44796da33f76ff8b5d1c35438","modified":1745754552989},{"_id":"source/_posts/test.md","hash":"649e9331925b959010ac09d5cb0cd3dd5668d753","modified":1768897539482},{"_id":"source/_posts/third-blog.md","hash":"cce6aa25172f79f95d6f6b4c1698900707859f9e","modified":1741700635558},{"_id":"source/link/index.md","hash":"0f8db9e31eeecd7269697077093998a5abe90b41","modified":1741158328831},{"_id":"source/_posts/sixth-blog.md","hash":"63f0c544bd8d5dc20781ccc304d06652d55f007f","modified":1744205580371},{"_id":"source/tags/index.md","hash":"3d0b2692fb8825924d8fcc7fe515d69c6da5b62c","modified":1741158339369},{"_id":"source/image/assetsavatar.jpg","hash":"ad999fd0592d79db084829d8235f2994faeb77dd","modified":1738832196933},{"_id":"source/image/A4.jpg","hash":"7f13c62270e85eee1104b1dfba10e194ae402771","modified":1741102727490},{"_id":"source/image/阿尼亚.jpg","hash":"243672015352325dd7b335323bd41925930fbb9d","modified":1741014914349},{"_id":"source/image/assetsbackground.jpg","hash":"75d1d4fce73023008d301027e6e1f0aec92a6bba","modified":1738913032012},{"_id":"source/image/微信图片_20250227225808.jpg","hash":"bea03f8956be7fa0233ca6258da737c0e0345525","modified":1740668294185},{"_id":"source/image/微信图片_20250311204951.jpg","hash":"a3634b1a56468b530e3821cf1b494aea6ad89ae9","modified":1741697398362},{"_id":"themes/butterfly/LICENSE","hash":"c8bc7df08db9dd3b39c2c2259a163a36cf2f6808","modified":1740402050231},{"_id":"themes/butterfly/.gitignore","hash":"1a22e577d9900e645b55d40d210e87c2a0d1221d","modified":1740402050231},{"_id":"themes/butterfly/README.md","hash":"e1b9096ae0c4e5ef0a911aec05dbad4a3aae3173","modified":1740402050231},{"_id":"themes/butterfly/package.json","hash":"9d57e4ef1e79d66d3561f2ce27c9a7083e34eadb","modified":1740402050269},{"_id":"themes/butterfly/.github/FUNDING.yml","hash":"3b572099a992e30267f5fe4cd3c582ff7ac9f083","modified":1740402050229},{"_id":"themes/butterfly/README_CN.md","hash":"92e45255b8725f0a00450c88fcfd51ec61e1db67","modified":1740402050231},{"_id":"themes/butterfly/plugins.yml","hash":"772322fd6b31cc785b3d376f44e9e953f501cc32","modified":1740402050269},{"_id":"themes/butterfly/languages/default.yml","hash":"a2c938b1ef69195aec10c90dc7d1871953548e01","modified":1740402050232},{"_id":"themes/butterfly/languages/ja.yml","hash":"a281d3cc3e117e90597b783dc5569dba3976d2eb","modified":1740402050233},{"_id":"themes/butterfly/languages/en.yml","hash":"a2c938b1ef69195aec10c90dc7d1871953548e01","modified":1740402050233},{"_id":"themes/butterfly/languages/zh-TW.yml","hash":"bd7ee35aa30964493d2729ef105bb86331b096c3","modified":1740402050235},{"_id":"themes/butterfly/languages/ko.yml","hash":"c7d861c58f204f47a5b4d6e118e1f1e8fb8a852f","modified":1740402050233},{"_id":"themes/butterfly/languages/zh-CN.yml","hash":"e0bf36edf18cf3380b900be7528b536252990c26","modified":1740402050234},{"_id":"themes/butterfly/languages/zh-HK.yml","hash":"bac3063ad2892be232f7d91361c28585a3cc7eb5","modified":1740402050235},{"_id":"themes/butterfly/layout/category.pug","hash":"a7e9805a781e34e38d27462e6ce2a5821c34bb9f","modified":1740402050236},{"_id":"themes/butterfly/layout/archive.pug","hash":"bc77220dfc269b8faad0930e1a4142ebf68165e5","modified":1740402050236},{"_id":"themes/butterfly/layout/page.pug","hash":"7ce2a49c6c41847de4ccea377ade116339984434","modified":1740402050266},{"_id":"themes/butterfly/layout/tag.pug","hash":"ca5333bd262cb58c195c844b593a0eed0c721766","modified":1740402050267},{"_id":"themes/butterfly/layout/post.pug","hash":"65c4a49c65c3fc4d9dc88b9791a75710c698c3a1","modified":1740402050267},{"_id":"themes/butterfly/layout/index.pug","hash":"a93004cc8ec8050df603d32a6e6e02cd96fd9875","modified":1740402050266},{"_id":"themes/butterfly/.github/ISSUE_TEMPLATE/bug_report.yml","hash":"10ce05c8dbde09f53bdabe40b5388de9ccc71a31","modified":1740402050229},{"_id":"themes/butterfly/layout/includes/additional-js.pug","hash":"f9b02aac0dbbb2b71c037dd215e70c8b7ec7741c","modified":1740402050236},{"_id":"themes/butterfly/.github/ISSUE_TEMPLATE/feature_request.yml","hash":"6e0f9470b18bd37d4891282ac73d61676b040e8c","modified":1740402050230},{"_id":"themes/butterfly/.github/workflows/stale.yml","hash":"4040c76547e270aaf184e9b219a44ca41bbb1b9f","modified":1740402050230},{"_id":"themes/butterfly/.github/workflows/publish.yml","hash":"e320b40c051bae1549156cd5ea4a51383cf78598","modified":1740402050230},{"_id":"themes/butterfly/layout/includes/footer.pug","hash":"6bd41add3a45e55d5e51eab5285a2d1a909d37f3","modified":1740402050236},{"_id":"themes/butterfly/layout/includes/head.pug","hash":"1d11e334b22dbbedcb0f751f9ee9789d4416605e","modified":1740402050237},{"_id":"themes/butterfly/layout/includes/layout.pug","hash":"e5e6c05a621483b3542f2884e8ba45e84b1e973a","modified":1740402050241},{"_id":"themes/butterfly/layout/includes/pagination.pug","hash":"bd45e6fa935ace9cb54499b0491dacfb78ccc354","modified":1740402050244},{"_id":"themes/butterfly/_config.butterfly.yml","hash":"0d6795c29bb3ceccec5760e5dacf34c6d4a37e32","modified":1740751368794},{"_id":"themes/butterfly/layout/includes/sidebar.pug","hash":"3e65b7bf6bccccbba7e15349f0a44f15c64c5b5e","modified":1740402050247},{"_id":"themes/butterfly/layout/includes/rightside.pug","hash":"43f951b639038f3bc01deea03368d8dcf492cbb0","modified":1740402050246},{"_id":"themes/butterfly/scripts/events/404.js","hash":"039fc75f363d79669b0b2177d929cdff6f2ef7a4","modified":1740402050270},{"_id":"themes/butterfly/scripts/events/cdn.js","hash":"7864ba45716c51aef8d8b04fd4bc212e0008ce3b","modified":1740402050270},{"_id":"themes/butterfly/scripts/events/comment.js","hash":"7b1b16e1e8e08245a345764616956be50487eb53","modified":1740402050270},{"_id":"themes/butterfly/scripts/events/init.js","hash":"ce68e84a9ccfcf91100befbaa9afc392a0cd93bb","modified":1740402050270},{"_id":"themes/butterfly/scripts/helpers/aside_archives.js","hash":"3eb0bbb1288dc7b0ff82cc46ceb53bd666893416","modified":1740402050272},{"_id":"themes/butterfly/scripts/common/postDesc.js","hash":"272613a71d16f0de6dac883be4839259f774be76","modified":1740402050269},{"_id":"themes/butterfly/scripts/events/merge_config.js","hash":"10ffed853a935498f1f5da2c5b57200c957874a7","modified":1740402050271},{"_id":"themes/butterfly/scripts/events/stylus.js","hash":"bac639c404588ea62e601ef0bcd368c3bd0119af","modified":1740402050271},{"_id":"themes/butterfly/.github/ISSUE_TEMPLATE/config.yml","hash":"63ad2249ad09fb3fe21bd5ff9adefb304a7ab24a","modified":1740402050229},{"_id":"themes/butterfly/scripts/events/welcome.js","hash":"f59e10305fef59ea3e62a7395106c0927582879d","modified":1740402050271},{"_id":"themes/butterfly/scripts/helpers/inject_head_js.js","hash":"088493dca2a157b49d232db482ef916207240b46","modified":1740402050273},{"_id":"themes/butterfly/scripts/helpers/aside_categories.js","hash":"0cdf781a8c14d7b50d309e69f282ec7b178804bb","modified":1740402050272},{"_id":"themes/butterfly/scripts/helpers/page.js","hash":"a07b586b510aa2df953102d998e84207acc34f9b","modified":1740402050273},{"_id":"themes/butterfly/scripts/helpers/related_post.js","hash":"950b7d0966429bf0f9e6c5e1161e50e545e320b4","modified":1740402050273},{"_id":"themes/butterfly/scripts/helpers/series.js","hash":"45367c4ce827329867dbcc750ec125da9ccb2cfd","modified":1740402050274},{"_id":"themes/butterfly/scripts/filters/post_lazyload.js","hash":"b23108d29fff3e32384d8689c8bcd2ab306a1ae7","modified":1740402050271},{"_id":"themes/butterfly/scripts/filters/random_cover.js","hash":"20a6ebf63439501a4b3fc81e7a2a2ea5d103bace","modified":1740402050272},{"_id":"themes/butterfly/scripts/tag/flink.js","hash":"25eefe10189caf3910a0e5d5b2f2043ae9255531","modified":1740402050274},{"_id":"themes/butterfly/scripts/tag/button.js","hash":"2f44e1b3ccd170b256eae178299d6fa933a8d490","modified":1740402050274},{"_id":"themes/butterfly/scripts/tag/chartjs.js","hash":"195ba802d7e8406c155124a9c939a2318f82938b","modified":1740402050274},{"_id":"themes/butterfly/scripts/helpers/getArchiveLength.js","hash":"bf77635e920eaf52bceebc95f87c7c87a7ca8038","modified":1740402050273},{"_id":"themes/butterfly/scripts/tag/gallery.js","hash":"fa3d0a64f7fce4aff7928d4ddd95548978ba001c","modified":1740402050275},{"_id":"themes/butterfly/scripts/tag/inlineImg.js","hash":"89c6c78d2db43b190055d5690741a79bab4f3e7e","modified":1740402050275},{"_id":"themes/butterfly/scripts/tag/label.js","hash":"cf0bc17d0180231167cc6aa8a00fc64f198cb9f9","modified":1740402050275},{"_id":"themes/butterfly/scripts/tag/hide.js","hash":"f02fb085a88a2c0c82aeffacc24e1b71c74bd7c0","modified":1740402050275},{"_id":"themes/butterfly/scripts/tag/note.js","hash":"e68d8d21f3a86e3646907a3685550ee20e8d4a9f","modified":1740402050276},{"_id":"themes/butterfly/scripts/tag/mermaid.js","hash":"50d8d8fac5c5b6e26317028895d7d82a2cf46606","modified":1740402050276},{"_id":"themes/butterfly/scripts/tag/score.js","hash":"35d54adc92e717cc32e13515122b025fd1a98ea2","modified":1740402050276},{"_id":"themes/butterfly/scripts/tag/timeline.js","hash":"176804f07567aa80f1ed95897a968a996b155dec","modified":1740402050277},{"_id":"themes/butterfly/scripts/tag/series.js","hash":"40bc9a065e3a1423e0e66f4911e00713ca9f5e9e","modified":1740402050276},{"_id":"themes/butterfly/source/css/index.styl","hash":"b13d96924a5534bff91d75566b196ac87b4fac22","modified":1740402050296},{"_id":"themes/butterfly/scripts/tag/tabs.js","hash":"3c486b149e28edd1a06843f05a5c355000991b82","modified":1740402050276},{"_id":"themes/butterfly/source/js/main.js","hash":"5a52047b8520f79864d5a4ee2379a29751aead23","modified":1740402050303},{"_id":"themes/butterfly/source/js/tw_cn.js","hash":"fdb5482d04a75bd79946ad1ed291d281d0e9362d","modified":1740402050304},{"_id":"themes/butterfly/source/img/404.jpg","hash":"fb4489bc1d30c93d28f7332158c1c6c1416148de","modified":1740402050297},{"_id":"themes/butterfly/source/js/utils.js","hash":"48637ad8e405306772b93837f33400bde1055819","modified":1740402050305},{"_id":"themes/butterfly/source/img/favicon.ico","hash":"455ac256580bf31a45813dbbdb87219bfc8bfb04","modified":1740402050302},{"_id":"themes/butterfly/source/img/friend_404.gif","hash":"8d2d0ebef70a8eb07329f57e645889b0e420fa48","modified":1740402050303},{"_id":"themes/butterfly/source/css/var.styl","hash":"424e251f17393b8e644c3942df4f61d0cd84e682","modified":1741360673409},{"_id":"themes/butterfly/source/img/error-page.png","hash":"d2519710498a871ca3e913c57e2ba20a805b6430","modified":1740402050301},{"_id":"themes/butterfly/layout/includes/head/analytics.pug","hash":"e792a435afee1f9491095084a00dc77e3522c1fd","modified":1740402050238},{"_id":"themes/butterfly/layout/includes/head/config.pug","hash":"9ea75b06f19bf356f340f4a3fc1bdc0713cfe445","modified":1740402050238},{"_id":"themes/butterfly/layout/includes/head/Open_Graph.pug","hash":"e93a36d3c29b5a02c7f26a23f96e1f84b063cbe8","modified":1740402050237},{"_id":"themes/butterfly/layout/includes/head/config_site.pug","hash":"56a3c32de1a15627ff38c67f1131cdd6ec5ac924","modified":1740402050238},{"_id":"themes/butterfly/layout/includes/head/pwa.pug","hash":"83ed05ef1e39f2ee70c3fba2cf96e488d8ffec66","modified":1740402050239},{"_id":"themes/butterfly/layout/includes/head/preconnect.pug","hash":"1e1a69aa2cbda2e621c741b3802093244b3cc04e","modified":1740402050239},{"_id":"themes/butterfly/layout/includes/head/site_verification.pug","hash":"5168caadc4cf541f5d6676a9c5e8ae47a948f9ad","modified":1740402050239},{"_id":"themes/butterfly/layout/includes/head/google_adsense.pug","hash":"f29123e603cbbcc6ce277d4e8f600ba67498077c","modified":1740402050238},{"_id":"themes/butterfly/layout/includes/head/structured_data.pug","hash":"1b83ae33961528f128596753fd05067c672d6bff","modified":1740402050239},{"_id":"themes/butterfly/layout/includes/header/post-info.pug","hash":"7d799c4694adb6e265e3f4b975d7f7f6a7021a17","modified":1740402050241},{"_id":"themes/butterfly/layout/includes/header/index.pug","hash":"44331c9db74b281b5c5c41439d3407a9076df1a1","modified":1740402050240},{"_id":"themes/butterfly/layout/includes/header/nav.pug","hash":"18b984ce184ea53d2dff5a03cc2d0d39d2ec3406","modified":1740402050240},{"_id":"themes/butterfly/layout/includes/header/menu_item.pug","hash":"733184f88e3a586a5fcc9d193ad500556b6c8eed","modified":1740402050240},{"_id":"themes/butterfly/source/css/background.css","hash":"eaee2a8bfc16f682b0d6eaae02a6e5b3aa6d87c7","modified":1740750233291},{"_id":"themes/butterfly/layout/includes/header/social.pug","hash":"e2d31e0f450ad42c47f7ee96375799342bf2f19b","modified":1740402050241},{"_id":"themes/butterfly/layout/includes/loading/index.pug","hash":"d76ce71ba106e350670c021a3dcae57547d01830","modified":1740402050242},{"_id":"themes/butterfly/layout/includes/post/post-copyright.pug","hash":"b96c232e5178d927987791d9ae386dd83679535a","modified":1740402050246},{"_id":"themes/butterfly/layout/includes/mixins/article-sort.pug","hash":"ef7afe0df7a3746744ac8185da7163b7406120ca","modified":1740402050242},{"_id":"themes/butterfly/layout/includes/mixins/indexPostUI.pug","hash":"f3389fa9ae4fa32e3c16573286583bc3023e57ad","modified":1740402050243},{"_id":"themes/butterfly/layout/includes/post/outdate-notice.pug","hash":"b7ce9484bc5c97ea6154f0b78fb9b8951fafedbd","modified":1740402050246},{"_id":"themes/butterfly/layout/includes/loading/pace.pug","hash":"9d2d539555bab495959b9df734ed5c43a9f9e5a9","modified":1740402050242},{"_id":"themes/butterfly/layout/includes/page/404.pug","hash":"15d32c511e4875066fcbe9cb84c3ada07b5a7c41","modified":1740402050243},{"_id":"themes/butterfly/layout/includes/post/reward.pug","hash":"db92f25ff3fd061882f81bf74ca560ff66983a0c","modified":1740402050246},{"_id":"themes/butterfly/layout/includes/page/default-page.pug","hash":"efb40388e37cca0b5e7c3c66e811a42f8d32c910","modified":1740402050243},{"_id":"themes/butterfly/layout/includes/page/categories.pug","hash":"5276a8d2835e05bd535fedc9f593a0ce8c3e8437","modified":1740402050243},{"_id":"themes/butterfly/layout/includes/page/flink.pug","hash":"6b0fa5f048aca8e9cbe56978301af918cf7ac34a","modified":1740402050244},{"_id":"themes/butterfly/layout/includes/page/tags.pug","hash":"79ad31eb72a9e14007770b18a426406a25315b38","modified":1740402050244},{"_id":"themes/butterfly/layout/includes/third-party/aplayer.pug","hash":"ed79fef5b5025415ea12eaed970f3fe7f6ef9596","modified":1740402050247},{"_id":"themes/butterfly/layout/includes/page/shuoshuo.pug","hash":"b2423cfc57a5e3a0e1112ff7c18d5c5c720d89d5","modified":1740402050244},{"_id":"themes/butterfly/layout/includes/third-party/effect.pug","hash":"43014bfc63583d3ee8808d526dd165848c0ed52f","modified":1740402050256},{"_id":"themes/butterfly/layout/includes/third-party/pjax.pug","hash":"e9b3d4d20e69e5051dded50c803c212946d443c0","modified":1740402050260},{"_id":"themes/butterfly/layout/includes/third-party/prismjs.pug","hash":"88f979a0b1a19eeb0db229247833bf9c6865c3b9","modified":1740402050261},{"_id":"themes/butterfly/layout/includes/widget/card_ad.pug","hash":"a8312b527493dabbadbb1280760168d3bc909a3b","modified":1740402050263},{"_id":"themes/butterfly/layout/includes/third-party/subtitle.pug","hash":"a11455e294d32d2795eb1ee9d54a2906f064a1cb","modified":1740402050263},{"_id":"themes/butterfly/layout/includes/third-party/umami_analytics.pug","hash":"bc35a1552d26ecdeeadbf06300078dbb5128a6e5","modified":1740402050263},{"_id":"themes/butterfly/layout/includes/widget/card_announcement.pug","hash":"21e019bdc3b1e796bb00976bb29af2d51f873624","modified":1740402050263},{"_id":"themes/butterfly/layout/includes/widget/card_newest_comment.pug","hash":"d8753772889b5d0f4d15639ed6af5e91e53b1d03","modified":1740402050264},{"_id":"themes/butterfly/layout/includes/widget/card_archives.pug","hash":"73d33b6930e7944187a4b3403daf25d27077a2dd","modified":1740402050264},{"_id":"themes/butterfly/layout/includes/widget/card_author.pug","hash":"1aba8aa7cd767dc96879d13a13b4c8ceb9023233","modified":1740402050264},{"_id":"themes/butterfly/layout/includes/widget/card_categories.pug","hash":"66e383b4ef374951eb87dd1bf4cdb7a667193fb5","modified":1740402050264},{"_id":"themes/butterfly/layout/includes/widget/card_bottom_self.pug","hash":"1dba77d250eeebfb6e293d504352c7e9ea31980b","modified":1740402050264},{"_id":"themes/butterfly/layout/includes/widget/card_post_series.pug","hash":"e0bb72fa0ce15964b11b8fe421cae3432394e35f","modified":1740402050265},{"_id":"themes/butterfly/layout/includes/widget/card_post_toc.pug","hash":"1dd19a564320d248dbcee7f118a5b96c6466da65","modified":1740402050265},{"_id":"themes/butterfly/layout/includes/widget/card_tags.pug","hash":"842b772a387b576550fa127030e1c2e9bf65716d","modified":1740402050265},{"_id":"themes/butterfly/layout/includes/widget/card_top_self.pug","hash":"7b5ae404a1205546b7de4be42291315cf918f2b3","modified":1740402050266},{"_id":"themes/butterfly/layout/includes/widget/card_recent_post.pug","hash":"bb842d2aa6469d65bf06af1372f0a19a9e4ef44c","modified":1740402050265},{"_id":"themes/butterfly/layout/includes/widget/index.pug","hash":"45f620cd87b9ef2aa9d1e024e697ed6b4eecff34","modified":1740402050266},{"_id":"themes/butterfly/layout/includes/widget/card_webinfo.pug","hash":"fcddd80cdeb6aa81f342cd9f0102302f6ba087a8","modified":1740402050266},{"_id":"themes/butterfly/source/css/_global/index.styl","hash":"814053dd7499284a5c185382eb43c8f8db25baf2","modified":1740402050278},{"_id":"themes/butterfly/source/css/_layout/comments.styl","hash":"fbfce4d67cacd1df22fb73d89d008693f59d9d91","modified":1740402050287},{"_id":"themes/butterfly/source/css/_layout/aside.styl","hash":"ba174889e770ae9f6683379b9eae9d8c94253080","modified":1740402050286},{"_id":"themes/butterfly/source/css/_layout/footer.styl","hash":"d7b988d8588207086670f39aa49fce442c429f7a","modified":1740402050287},{"_id":"themes/butterfly/source/css/_layout/chat.styl","hash":"4cc02bcbaa4a1933a82a9ea57a603fe2d059fc77","modified":1740402050287},{"_id":"themes/butterfly/source/css/_global/function.styl","hash":"d12340a7df4601b9a23f070e16645861aeb3bb0a","modified":1740402050277},{"_id":"themes/butterfly/source/css/_layout/loading.styl","hash":"f0b01bbf321c2c24fdccaee367dd9fd448031a72","modified":1740402050288},{"_id":"themes/butterfly/layout/includes/loading/fullpage-loading.pug","hash":"a2f7d69ca7ec58f24fe7d4e04ae21d5b62b01567","modified":1740402050242},{"_id":"themes/butterfly/source/css/_layout/head.styl","hash":"094108f2a4e351a2fa496d6bd3e2388151416b3f","modified":1740402050287},{"_id":"themes/butterfly/source/css/_layout/post.styl","hash":"543eaf9c7df7e0db841e5946ee5f9082c3c46290","modified":1740402050288},{"_id":"themes/butterfly/source/css/_layout/relatedposts.styl","hash":"ef8e8549fe7ad4b99793844a93b4a89f77f417d5","modified":1740402050288},{"_id":"themes/butterfly/source/css/_layout/pagination.styl","hash":"7d7554573c005399bc8c2264a85896d2d51be1e1","modified":1740402050288},{"_id":"themes/butterfly/source/css/_layout/third-party.styl","hash":"0af7c8754f04bdd9a02a14d880774753bd2e35ee","modified":1740402050289},{"_id":"themes/butterfly/source/css/_layout/reward.styl","hash":"d9cdf564a822a585e67fd5bac8573ba87eeb3743","modified":1740402050289},{"_id":"themes/butterfly/source/css/_layout/rightside.styl","hash":"a0f5835f04358122e8b1d38dd3e8da09a1b5b431","modified":1740402050289},{"_id":"themes/butterfly/source/css/_layout/sidebar.styl","hash":"084dc4dfb41f55e237a9d6cf8c2f5dba729b83be","modified":1740402050289},{"_id":"themes/butterfly/source/css/_page/archives.styl","hash":"5abe5480d83ff8b452a780a484d50a44091475bf","modified":1740402050291},{"_id":"themes/butterfly/source/css/_page/404.styl","hash":"205ccc7d0ec6ce1193b46bc0c9ce0385594581fb","modified":1740402050290},{"_id":"themes/butterfly/source/css/_page/common.styl","hash":"dcff804c4c237e1e908481b44c1ac4e39ac0da34","modified":1740402050291},{"_id":"themes/butterfly/source/css/_page/categories.styl","hash":"c4cda7b0c99015df29ce00fdfddd2f7679653754","modified":1740402050291},{"_id":"themes/butterfly/source/css/_page/tags.styl","hash":"7543bb688876a946538d66b991c71b94b5216277","modified":1740402050292},{"_id":"themes/butterfly/source/css/_page/flink.styl","hash":"1f8d715faf3b91b53426e38195c0920afb3bfa1c","modified":1740402050291},{"_id":"themes/butterfly/source/css/_page/shuoshuo.styl","hash":"79bb1d9a27822ed5675d1e52f5dbd0e2f5d5010a","modified":1740402050292},{"_id":"themes/butterfly/source/css/_tags/button.styl","hash":"de8437a058a315d14d7e7034066f095b7b3ed4b4","modified":1740402050294},{"_id":"themes/butterfly/source/css/_page/homepage.styl","hash":"992d192db7d1c96e995b85ed11c20c571d33fbad","modified":1740402050292},{"_id":"themes/butterfly/source/css/_tags/label.styl","hash":"216f52fefc2274b542b549d8470503e6f1a308fb","modified":1740402050295},{"_id":"themes/butterfly/source/css/_tags/hide.styl","hash":"d27dbccaf3de1c9158d19e4fd49a25953cb5778d","modified":1740402050294},{"_id":"themes/butterfly/source/css/_tags/gallery.styl","hash":"30d1f809efd252ed0233d96d4374efd2b01d2292","modified":1740402050294},{"_id":"themes/butterfly/source/css/_tags/note.styl","hash":"4929382bd60788d34752a66e2fe764ef797a72a0","modified":1740402050295},{"_id":"themes/butterfly/source/css/_tags/inlineImg.styl","hash":"3be8d0a75e7cc96548667cae0cb6a474279bd0b5","modified":1740402050295},{"_id":"themes/butterfly/source/css/_tags/hexo.styl","hash":"985b183db7b7bfd8f9bdb60494549fb7f850348b","modified":1740402050294},{"_id":"themes/butterfly/source/css/_tags/tabs.styl","hash":"dfbce718d528dd241664ff8fd28b37da92c29cef","modified":1740402050296},{"_id":"themes/butterfly/source/css/_tags/series.styl","hash":"0657169849bc4bf4d93b5492ade040c8f58c1901","modified":1740402050295},{"_id":"themes/butterfly/source/css/_highlight/theme.styl","hash":"a51edfd3e499e7d38c32241c40e8e4d371efca73","modified":1740402050286},{"_id":"themes/butterfly/source/css/_highlight/highlight.styl","hash":"67062d597408068e4a59e95851e98fed34b745da","modified":1740402050278},{"_id":"themes/butterfly/source/css/_tags/timeline.styl","hash":"e846ddaef494d46cdfa2379deacfe74fa1cc5264","modified":1740402050296},{"_id":"themes/butterfly/source/css/_search/algolia.styl","hash":"d8a8275a68a1421c4c09b604cf78bea16c1d0463","modified":1740402050292},{"_id":"themes/butterfly/source/css/_mode/darkmode.styl","hash":"93fe5a7ed83ceb11b888f946be94cf1ee7648f8c","modified":1740402050290},{"_id":"themes/butterfly/source/css/_search/local-search.styl","hash":"1f2b86df86df81c3a59377b29102314ffc73dfa6","modified":1740402050293},{"_id":"themes/butterfly/source/css/_mode/readmode.styl","hash":"ad66212554468b7067590308ed4cf40524fea662","modified":1740402050290},{"_id":"themes/butterfly/source/css/_search/index.styl","hash":"6c4cbdadd9a49029fe0c59e29808d873e5b6b6ee","modified":1740402050293},{"_id":"themes/butterfly/source/js/search/local-search.js","hash":"a2b783230a9143de69004cfc914d9f55e6fc1660","modified":1740402050304},{"_id":"themes/butterfly/source/css/_third-party/normalize.min.css","hash":"8549829fb7d3c21cd9e119884962e8c463a4a267","modified":1740402050296},{"_id":"themes/butterfly/source/js/search/algolia.js","hash":"7119f2f2943de71999d3dd6ba5c60cde846f114b","modified":1740402050304},{"_id":"themes/butterfly/layout/includes/third-party/abcjs/abcjs.pug","hash":"00b4073dbe0687a80e6d58c104c6f59ec01a84fd","modified":1740402050247},{"_id":"themes/butterfly/layout/includes/third-party/chat/crisp.pug","hash":"24d094fd917947c0ca7492fa094328b1a183b873","modified":1740402050251},{"_id":"themes/butterfly/layout/includes/third-party/chat/tidio.pug","hash":"62466b251052cae609b6369d4cb4b6a85320757d","modified":1740402050251},{"_id":"themes/butterfly/layout/includes/third-party/chat/chatra.pug","hash":"5b29badecbbe828112c001156023fc0566045cf6","modified":1740402050250},{"_id":"themes/butterfly/layout/includes/third-party/chat/index.pug","hash":"e8438941085def0591a72fc9b0d705dbf107f54f","modified":1740402050251},{"_id":"themes/butterfly/layout/includes/third-party/abcjs/index.pug","hash":"f0a90d8e39915a74b16ef22e851f179415cd7eaa","modified":1740402050247},{"_id":"themes/butterfly/layout/includes/third-party/card-post-count/artalk.pug","hash":"b03ee8625149191f9d5d057bbc9824b68d8dd0c4","modified":1740402050248},{"_id":"themes/butterfly/layout/includes/third-party/card-post-count/disqus.pug","hash":"d6fff5a7f84c8b09f282f9ddc0020a68a8aac9ea","modified":1740402050248},{"_id":"themes/butterfly/layout/includes/third-party/card-post-count/fb.pug","hash":"cbfbcf34a24d21ba2b21cf9eedb76f4c3c563c5a","modified":1740402050248},{"_id":"themes/butterfly/layout/includes/third-party/card-post-count/remark42.pug","hash":"716dc463fe4ef5112e7018ed60804125fdfa5cad","modified":1740402050249},{"_id":"themes/butterfly/layout/includes/third-party/card-post-count/index.pug","hash":"846cabae287ae31b3bbfac3da022475713dd5ecc","modified":1740402050248},{"_id":"themes/butterfly/layout/includes/third-party/card-post-count/valine.pug","hash":"7884883ec15792f7e54daacb3c62b851dde2b66a","modified":1740402050249},{"_id":"themes/butterfly/layout/includes/third-party/card-post-count/twikoo.pug","hash":"b5db4203a1392385838c73549ddeae0a4be67eba","modified":1740402050249},{"_id":"themes/butterfly/layout/includes/third-party/comments/artalk.pug","hash":"89c63a5f0c0ab6314de7158fbc8fcbc84997fc55","modified":1740402050252},{"_id":"themes/butterfly/layout/includes/third-party/card-post-count/waline.pug","hash":"fd2320ee25507bb8ef49f932c2d170586b44ea4d","modified":1740402050249},{"_id":"themes/butterfly/layout/includes/third-party/comments/gitalk.pug","hash":"58914c58a190e3bc0aa37cb581e77e442b563501","modified":1740402050253},{"_id":"themes/butterfly/layout/includes/third-party/comments/giscus.pug","hash":"592b2251db6c1abeb8b0eebe3b2e6d9aa0dec445","modified":1740402050253},{"_id":"themes/butterfly/layout/includes/third-party/comments/disqus.pug","hash":"f2ea5249b3e6670f6c8c77868f4f42c502e43830","modified":1740402050252},{"_id":"themes/butterfly/layout/includes/third-party/comments/facebook_comments.pug","hash":"8af585e6d6f73ee57114eefad574dc6e8ea9f570","modified":1740402050253},{"_id":"themes/butterfly/layout/includes/third-party/comments/disqusjs.pug","hash":"c81fa7d8a5cb96d1ae07bfa8c46b84a58161add1","modified":1740402050252},{"_id":"themes/butterfly/layout/includes/third-party/comments/livere.pug","hash":"7a80231fc71822e503879383a2d9611edf1d72dd","modified":1740402050254},{"_id":"themes/butterfly/layout/includes/third-party/comments/remark42.pug","hash":"84f7cfde00f929fa3dc40349bcab060ec68f1b9f","modified":1740402050254},{"_id":"themes/butterfly/layout/includes/third-party/comments/js.pug","hash":"3abbaaa4ea575c45b3cebffd40bad1acc6ffce84","modified":1740402050254},{"_id":"themes/butterfly/layout/includes/third-party/comments/waline.pug","hash":"e2bf15357485cd502414b3b20f5b1f762a2fd014","modified":1740402050256},{"_id":"themes/butterfly/layout/includes/third-party/comments/index.pug","hash":"db6713d2b90eb8183f86ac92c26761a8501c0ddb","modified":1740402050253},{"_id":"themes/butterfly/layout/includes/third-party/comments/twikoo.pug","hash":"53d99831f29aeb2e336ed1407d79590041f77002","modified":1740402050254},{"_id":"themes/butterfly/layout/includes/third-party/math/chartjs.pug","hash":"732eb1118ea1a73aa5c164d639097c614f8e9953","modified":1740402050257},{"_id":"themes/butterfly/layout/includes/third-party/comments/valine.pug","hash":"24f18b0c67803210d53abbf9c1d454c000b06eee","modified":1740402050256},{"_id":"themes/butterfly/layout/includes/third-party/comments/utterances.pug","hash":"30a7d157890de69deab28baa47fb7bb28b040efd","modified":1740402050256},{"_id":"themes/butterfly/layout/includes/third-party/math/index.pug","hash":"af66d13204030d47537b9e31a6173e63589ce7ff","modified":1740402050257},{"_id":"themes/butterfly/layout/includes/third-party/math/katex.pug","hash":"b83db9fa64d42a0bfd97efb660e09be3f166a144","modified":1740402050257},{"_id":"themes/butterfly/layout/includes/third-party/math/mermaid.pug","hash":"ca2fc5928ca292f29fd8333c73733344994096fb","modified":1740402050258},{"_id":"themes/butterfly/layout/includes/third-party/math/mathjax.pug","hash":"db2f4fff80a1166476ea76ae004aa186df11bad3","modified":1740402050257},{"_id":"themes/butterfly/layout/includes/third-party/newest-comments/common.pug","hash":"27fa75affebc6e84a487c62bceff783bde595256","modified":1740402050258},{"_id":"themes/butterfly/layout/includes/third-party/newest-comments/artalk.pug","hash":"187302dbc916852ff2fdf47061e272c061611dda","modified":1740402050258},{"_id":"themes/butterfly/layout/includes/third-party/newest-comments/github-issues.pug","hash":"72e2970b23570e308f8af5d8ba8e5e3321d01bbf","modified":1740402050259},{"_id":"themes/butterfly/layout/includes/third-party/newest-comments/index.pug","hash":"a7c07dbc1e970a5b247091458e1ee9b144a3366d","modified":1740402050259},{"_id":"themes/butterfly/layout/includes/third-party/newest-comments/remark42.pug","hash":"34edfebf0cace0852806be774910ccb0e0914650","modified":1740402050259},{"_id":"themes/butterfly/layout/includes/third-party/newest-comments/waline.pug","hash":"ec6c685080634ac46ffbea1b8f10313388888f43","modified":1740402050260},{"_id":"themes/butterfly/layout/includes/third-party/newest-comments/valine.pug","hash":"d376ec17fb19fcdcf0d2ad71330190146d3af879","modified":1740402050260},{"_id":"themes/butterfly/layout/includes/third-party/search/algolia.pug","hash":"7f0ede1cd3fed2669c94a8e1b21bc0b183f310b8","modified":1740402050261},{"_id":"themes/butterfly/layout/includes/third-party/newest-comments/twikoo-comment.pug","hash":"d2e12a9fc302a4efe52c90d44896fbd73e193a1f","modified":1740402050260},{"_id":"themes/butterfly/layout/includes/third-party/search/docsearch.pug","hash":"013756ff3363344987cc00fc9bd833baf193c341","modified":1740402050261},{"_id":"themes/butterfly/layout/includes/third-party/newest-comments/disqus-comment.pug","hash":"fa4b4194749d05f7249f365f2b89c0281057ce54","modified":1740402050259},{"_id":"themes/butterfly/layout/includes/third-party/search/index.pug","hash":"f8557548d2ad8dd149c562193991c6c6cda02415","modified":1740402050261},{"_id":"themes/butterfly/layout/includes/third-party/search/local-search.pug","hash":"2622b4cf9189fa23e4a422aaf9ef272e4f2c6137","modified":1740402050262},{"_id":"themes/butterfly/layout/includes/third-party/share/addtoany.pug","hash":"5c944052280c5ed046d2cfeb54b0da8876af0ec6","modified":1740402050262},{"_id":"themes/butterfly/layout/includes/third-party/share/share-js.pug","hash":"efef352c1d122409575386bf3894dce8e87032e2","modified":1740402050262},{"_id":"themes/butterfly/source/css/_highlight/highlight/diff.styl","hash":"9f02598b5e4296aec6470639d4bac4c9ac46392e","modified":1740402050278},{"_id":"themes/butterfly/layout/includes/third-party/share/index.pug","hash":"e51e896ccb13900de38dc81cf44dc789e2418a12","modified":1740402050262},{"_id":"themes/butterfly/source/css/_highlight/prismjs/diff.styl","hash":"077ec530831be1d80e93da380406b9f5abd0918a","modified":1740402050285},{"_id":"themes/butterfly/source/css/_highlight/highlight/index.styl","hash":"ef52ebf1e8e751a412f9456fdaeee7d88afd9a72","modified":1740402050278},{"_id":"themes/butterfly/source/css/_highlight/prismjs/index.styl","hash":"1883c91d43bff10aae55122a21e0b064b6f5c9dd","modified":1740402050285},{"_id":"themes/butterfly/source/css/_highlight/prismjs/line-number.styl","hash":"de4bb5fc2dfca368b35e4c1109c92f7abc9e2245","modified":1740402050285},{"_id":"source/image/微信图片_20250227225819.jpg","hash":"bc8bdfad0abb97da3a43e0c593fa63850a6fa697","modified":1740668301434},{"_id":"source/image/山田凉.jpg","hash":"71dd9246a0258079ff5bf74ecb5e410f648317c4","modified":1740455442969},{"_id":"source/image/微信图片_20250410145107.jpg","hash":"dddd4ad62a22f6317ef248b638ad2b38bc60941a","modified":1744267869933},{"_id":"themes/butterfly/source/img/butterfly-icon.png","hash":"f5dd732fed5c3bcd4aa76bac3441bac8485fb432","modified":1740402050301},{"_id":"themes/butterfly/source/img/assetsbg-pattern.jpg","hash":"75d1d4fce73023008d301027e6e1f0aec92a6bba","modified":1738831959838},{"_id":"source/image/微信图片_20250410145115.png","hash":"70cf71b2d91223185e25af8bb6315084d2f801d2","modified":1744267895714},{"_id":"source/image/微信图片_20250227225824.jpg","hash":"5f75059df7746a0a5c3b5fc14e5d9a0272f4fe13","modified":1740668306889},{"_id":"source/image/微信图片_20250227225830.jpg","hash":"d6dfc584e833bb00190c3d7ce43cb6fc413cd72a","modified":1740668312382},{"_id":"source/music/M800001LjzC74ccFMh.mp3","hash":"0cbdee62c62af8bc636d05b00652ba6db9de89b6","modified":1740580214671},{"_id":"source/image/壁纸1.jpg","hash":"2c2a02d5fb3cbdb8ccd5479149f51bdd4f71528c","modified":1740456464881},{"_id":"public/comments/index.html","hash":"f941b7929f25f4041462921eb62442796b05e3f8","modified":1768899757103},{"_id":"public/link/index.html","hash":"c71e0cf52b5c1f0b371de6e5d5d2ef7941f0fc85","modified":1768899757103},{"_id":"public/tags/index.html","hash":"7146d789b9717a91be8cd3176c03df6ea57f476c","modified":1768899757103},{"_id":"public/2025/02/24/hello-world/index.html","hash":"380095912fde136ba4f6270698389706e617b54e","modified":1768899757103},{"_id":"public/2025/03/05/second-blog/index.html","hash":"557d2ff3b3c2848874083b07f68915e102609ea2","modified":1768899757103},{"_id":"public/2025/03/11/third-blog/index.html","hash":"85b6c96332d7bec88794c20e40b81a03ea852b78","modified":1768899757103},{"_id":"public/2025/02/24/first-blog/index.html","hash":"0454fe8192e2bde11f65d997f8ad164d1984c1d9","modified":1768899757103},{"_id":"public/2025/03/13/forth-blog/index.html","hash":"b1faafec17e1bb523bab8f381ec4ee2af1eaf5b3","modified":1768899757103},{"_id":"public/2025/03/29/fith-blog/index.html","hash":"7a00223aeb760fa9e3ad410ddfdf259540ab88ac","modified":1768899757103},{"_id":"public/2025/04/08/sixth-blog/index.html","hash":"5ec6063709f16c5f26498854875459149e27e7d7","modified":1768899757103},{"_id":"public/2025/04/10/siventh-bolg/index.html","hash":"e02bed2dd96176835ccbd8fd0edda08656bc942e","modified":1768899757103},{"_id":"public/2025/04/10/eigth-blog/index.html","hash":"0ecb09bbca4aa1bcb43e6950c8e638333c567c08","modified":1768899757103},{"_id":"public/2025/05/08/ninth-blog/index.html","hash":"2e50fb9ce9ad7f0d4e32f9d1e5f235b5fb5fdc31","modified":1768899757103},{"_id":"public/2025/06/17/C++1/index.html","hash":"b8cc94e9be93681fa302711b4fcd6a19042b9a74","modified":1768899757103},{"_id":"public/2026/01/20/test/index.html","hash":"fa9493211642975e96b249ba59f46dee5eac0d76","modified":1768899757103},{"_id":"public/archives/index.html","hash":"bd6ffe83911f2b63f3b980cdc11cc493262aaf6a","modified":1768899757103},{"_id":"public/archives/page/2/index.html","hash":"79d9c8bdb3858d4b0775e4c6f36dda2371861536","modified":1768899757103},{"_id":"public/archives/2025/index.html","hash":"544faf0bd06dcc62adec1babcd147dab99fe9ea3","modified":1768899757103},{"_id":"public/archives/2025/page/2/index.html","hash":"941fbfac2b572390eff6330d089ffbc4092401b2","modified":1768899757103},{"_id":"public/archives/2025/02/index.html","hash":"1e8e5860598baf6e58f6d00f11bd38464703f7d2","modified":1768899757103},{"_id":"public/archives/2025/03/index.html","hash":"80d3bcdc858afdb3e740c5daf77aad570072e85d","modified":1768899757103},{"_id":"public/archives/2025/04/index.html","hash":"e658d661c452682b78ff6c3768a7b4df2797e02a","modified":1768899757103},{"_id":"public/archives/2025/05/index.html","hash":"04bf5237b93a6e1f5a1ed1896852b2de16514540","modified":1768899757103},{"_id":"public/archives/2025/06/index.html","hash":"515f8c8fa394ef0f90424bc35ea97c7047d14e1a","modified":1768899757103},{"_id":"public/index.html","hash":"d8ffee4d9bd0d325c0e2ba6d188c5f1d3fe44de4","modified":1768899757103},{"_id":"public/archives/2026/index.html","hash":"e076522153487c43fe08353b1f6a3f29fc5b6863","modified":1768899757103},{"_id":"public/archives/2026/01/index.html","hash":"010bbeab3366b3dc853dde8f1f215e46014d2daa","modified":1768899757103},{"_id":"public/tags/算法/index.html","hash":"21525fc7dc13dde8740ee6132916bb0cb20ec8fd","modified":1768899757103},{"_id":"public/tags/C/index.html","hash":"be3c5fb4a7095915de4a0cea6bdceeb2641160c5","modified":1768899757103},{"_id":"public/tags/博客构建/index.html","hash":"9a91783d71bbeeeaa8e4cf1809b7409ae0c3d0a6","modified":1768899757103},{"_id":"public/page/2/index.html","hash":"7607b19e6f99293ae93c4172d834eda88cd98e35","modified":1768899757103},{"_id":"public/img/404.jpg","hash":"fb4489bc1d30c93d28f7332158c1c6c1416148de","modified":1768899757103},{"_id":"public/img/friend_404.gif","hash":"8d2d0ebef70a8eb07329f57e645889b0e420fa48","modified":1768899757103},{"_id":"public/img/favicon.ico","hash":"455ac256580bf31a45813dbbdb87219bfc8bfb04","modified":1768899757103},{"_id":"public/img/error-page.png","hash":"d2519710498a871ca3e913c57e2ba20a805b6430","modified":1768899757103},{"_id":"public/CNAME","hash":"c6a054ecc02b58fbde31263ca6f8e6b1a6465b43","modified":1768899757103},{"_id":"public/css/index.css","hash":"78a18f6a55a325ee9402d1a1f7b27e929de9fa1d","modified":1768899757103},{"_id":"public/css/var.css","hash":"da39a3ee5e6b4b0d3255bfef95601890afd80709","modified":1768899757103},{"_id":"public/css/background.css","hash":"c22976e0f2dd70226ffd29e595f8755744364f0a","modified":1768899757103},{"_id":"public/js/utils.js","hash":"fd3c26366c78dd82bc87d4ddebe76c582122e1b7","modified":1768899757103},{"_id":"public/js/search/algolia.js","hash":"e5821f78381af9f0f646952a7dd118daab2a79a6","modified":1768899757103},{"_id":"public/js/search/local-search.js","hash":"4e11d033fb58563f5e1b497f1a6f1c62d3501ee6","modified":1768899757103},{"_id":"public/js/tw_cn.js","hash":"7ef59df188ea523da89f4caf69c5c0f14e78da69","modified":1768899757103},{"_id":"public/js/main.js","hash":"fb746a3e67d0373deea8481110dd436fea4ca38c","modified":1768899757103},{"_id":"public/image/带宽_爱给网_aigei_com.png","hash":"aa72c854a315e5650471723aa12f9d9d9dab6288","modified":1768899757103},{"_id":"public/assets/css/APlayer.min.css","hash":"07372a2ba507388d0fed166d761b1c2c2a659dce","modified":1768899757103},{"_id":"public/assets/js/APlayer.min.js","hash":"22caa28ff6b41a16ff40f15d38f1739e22359478","modified":1768899757103},{"_id":"public/image/A4.jpg","hash":"7f13c62270e85eee1104b1dfba10e194ae402771","modified":1768899757103},{"_id":"public/assets/js/Meting.min.js","hash":"a0585220b918d78649a7893279e1ec4fb5abe835","modified":1768899757103},{"_id":"public/image/assetsavatar.jpg","hash":"ad999fd0592d79db084829d8235f2994faeb77dd","modified":1768899757103},{"_id":"public/image/阿尼亚.jpg","hash":"243672015352325dd7b335323bd41925930fbb9d","modified":1768899757103},{"_id":"public/img/butterfly-icon.png","hash":"f5dd732fed5c3bcd4aa76bac3441bac8485fb432","modified":1768899757103},{"_id":"public/img/assetsbg-pattern.jpg","hash":"75d1d4fce73023008d301027e6e1f0aec92a6bba","modified":1768899757103},{"_id":"public/image/assetsbackground.jpg","hash":"75d1d4fce73023008d301027e6e1f0aec92a6bba","modified":1768899757103},{"_id":"public/image/微信图片_20250227225808.jpg","hash":"bea03f8956be7fa0233ca6258da737c0e0345525","modified":1768899757103},{"_id":"public/image/微信图片_20250311204951.jpg","hash":"a3634b1a56468b530e3821cf1b494aea6ad89ae9","modified":1768899757103},{"_id":"public/image/微信图片_20250227225819.jpg","hash":"bc8bdfad0abb97da3a43e0c593fa63850a6fa697","modified":1768899757103},{"_id":"public/image/山田凉.jpg","hash":"71dd9246a0258079ff5bf74ecb5e410f648317c4","modified":1768899757103},{"_id":"public/image/微信图片_20250410145107.jpg","hash":"dddd4ad62a22f6317ef248b638ad2b38bc60941a","modified":1768899757103},{"_id":"public/image/微信图片_20250410145115.png","hash":"70cf71b2d91223185e25af8bb6315084d2f801d2","modified":1768899757103},{"_id":"public/image/微信图片_20250227225824.jpg","hash":"5f75059df7746a0a5c3b5fc14e5d9a0272f4fe13","modified":1768899757103},{"_id":"public/image/微信图片_20250227225830.jpg","hash":"d6dfc584e833bb00190c3d7ce43cb6fc413cd72a","modified":1768899757103},{"_id":"public/music/M800001LjzC74ccFMh.mp3","hash":"0cbdee62c62af8bc636d05b00652ba6db9de89b6","modified":1768899757103},{"_id":"public/image/壁纸1.jpg","hash":"2c2a02d5fb3cbdb8ccd5479149f51bdd4f71528c","modified":1768899757103}],"Category":[],"Data":[{"_id":"link","data":[{"class_name":"友情链接","class_desc":"那些人,那些事","link_list":[{"name":"Hexo","link":"https://hexo.io/zh-tw/","avatar":"https://d33wubrfki0l68.cloudfront.net/6657ba50e702d84afb32fe846bed54fba1a77add/827ae/logo.svg","descr":"快速、簡單且強大的網誌框架"},{"name":"羊习习","link":"https://shop1111.github.io/","avatar":"/image/阿尼亚.jpg","descr":"博客"},{"name":"My-Blog","link":"https://eisem.github.io/","avatar":"/image/A4.jpg","descr":"博客"},{"name":"哈哈哈","link":"https://zlhahaha.github.io","avatar":"/image/山田凉.jpg","descr":"博客"}]}]}],"Page":[{"title":"留言板","date":"2025-03-03T14:00:00.000Z","type":"comments","_content":"\n<!-- 留言板顶部定制代码 -->\n<style>\n/* 二次元浅蓝主色调 */\n#page {\n background: linear-gradient(150deg,rgb(252, 252, 252) 20%, #f0faff 80%);\n padding: 2rem !important;\n border-radius: 15px;\n box-shadow: 0 8px 20px rgba(16, 59, 95, 0.15);\n position: relative;\n overflow: hidden;\n}\n\n\n\n/* 标题样式 */\n.board-title {\n font-family: 'Ma Shan Zheng', cursive;\n color: #2196F3;\n text-shadow: 2px 2px 0px #BBDEFB;\n font-size: 2.5rem;\n border-bottom: 3px dashed #90CAF9;\n padding-bottom: 1rem;\n position: relative;\n z-index: 2;\n}\n\n\n\n/* 装饰图标 */\n.decor-icon {\n position: absolute;\n width: 80px;\n opacity: 0.8;\n transition: transform 0.3s ease;\n}\n\n.decor-icon.left {\n left: 20px;\n top: 50px;\n}\n\n.decor-icon.right {\n right: 20px;\n top: 40px;\n}\n</style>\n\n<div class=\"board-header\">\n \n <h1 class=\"board-title\"> 有什么想说的...</h1>\n \n \n <div class=\"welcome-text\">\n <p> ✨ 好吃的<br>\n ✨ 好玩的 <br> \n ✨ 都来说说吧 </p>\n </div>\n</div>\n","source":"comments/index.md","raw":"---\ntitle: 留言板\ndate: 2025-03-03 22:00:00\ntype: \"comments\"\n---\n\n<!-- 留言板顶部定制代码 -->\n<style>\n/* 二次元浅蓝主色调 */\n#page {\n background: linear-gradient(150deg,rgb(252, 252, 252) 20%, #f0faff 80%);\n padding: 2rem !important;\n border-radius: 15px;\n box-shadow: 0 8px 20px rgba(16, 59, 95, 0.15);\n position: relative;\n overflow: hidden;\n}\n\n\n\n/* 标题样式 */\n.board-title {\n font-family: 'Ma Shan Zheng', cursive;\n color: #2196F3;\n text-shadow: 2px 2px 0px #BBDEFB;\n font-size: 2.5rem;\n border-bottom: 3px dashed #90CAF9;\n padding-bottom: 1rem;\n position: relative;\n z-index: 2;\n}\n\n\n\n/* 装饰图标 */\n.decor-icon {\n position: absolute;\n width: 80px;\n opacity: 0.8;\n transition: transform 0.3s ease;\n}\n\n.decor-icon.left {\n left: 20px;\n top: 50px;\n}\n\n.decor-icon.right {\n right: 20px;\n top: 40px;\n}\n</style>\n\n<div class=\"board-header\">\n \n <h1 class=\"board-title\"> 有什么想说的...</h1>\n \n \n <div class=\"welcome-text\">\n <p> ✨ 好吃的<br>\n ✨ 好玩的 <br> \n ✨ 都来说说吧 </p>\n </div>\n</div>\n","updated":"2025-03-07T15:02:45.273Z","path":"comments/index.html","comments":1,"layout":"page","_id":"cmkmd8tym0000cw64avu0cktf","content":"<link rel=\"stylesheet\" class=\"aplayer-secondary-style-marker\" href=\"\\assets\\css\\APlayer.min.css\"><script src=\"\\assets\\js\\APlayer.min.js\" class=\"aplayer-secondary-script-marker\"></script><!-- 留言板顶部定制代码 -->\n<style>\n/* 二次元浅蓝主色调 */\n#page {\n background: linear-gradient(150deg,rgb(252, 252, 252) 20%, #f0faff 80%);\n padding: 2rem !important;\n border-radius: 15px;\n box-shadow: 0 8px 20px rgba(16, 59, 95, 0.15);\n position: relative;\n overflow: hidden;\n}\n\n\n\n/* 标题样式 */\n.board-title {\n font-family: 'Ma Shan Zheng', cursive;\n color: #2196F3;\n text-shadow: 2px 2px 0px #BBDEFB;\n font-size: 2.5rem;\n border-bottom: 3px dashed #90CAF9;\n padding-bottom: 1rem;\n position: relative;\n z-index: 2;\n}\n\n\n\n/* 装饰图标 */\n.decor-icon {\n position: absolute;\n width: 80px;\n opacity: 0.8;\n transition: transform 0.3s ease;\n}\n\n.decor-icon.left {\n left: 20px;\n top: 50px;\n}\n\n.decor-icon.right {\n right: 20px;\n top: 40px;\n}\n</style>\n\n<div class=\"board-header\">\n \n <h1 class=\"board-title\"> 有什么想说的...</h1>\n \n \n <div class=\"welcome-text\">\n <p> ✨ 好吃的<br>\n ✨ 好玩的 <br> \n ✨ 都来说说吧 </p>\n </div>\n</div>\n","excerpt":"","more":"<!-- 留言板顶部定制代码 -->\n<style>\n/* 二次元浅蓝主色调 */\n#page {\n background: linear-gradient(150deg,rgb(252, 252, 252) 20%, #f0faff 80%);\n padding: 2rem !important;\n border-radius: 15px;\n box-shadow: 0 8px 20px rgba(16, 59, 95, 0.15);\n position: relative;\n overflow: hidden;\n}\n\n\n\n/* 标题样式 */\n.board-title {\n font-family: 'Ma Shan Zheng', cursive;\n color: #2196F3;\n text-shadow: 2px 2px 0px #BBDEFB;\n font-size: 2.5rem;\n border-bottom: 3px dashed #90CAF9;\n padding-bottom: 1rem;\n position: relative;\n z-index: 2;\n}\n\n\n\n/* 装饰图标 */\n.decor-icon {\n position: absolute;\n width: 80px;\n opacity: 0.8;\n transition: transform 0.3s ease;\n}\n\n.decor-icon.left {\n left: 20px;\n top: 50px;\n}\n\n.decor-icon.right {\n right: 20px;\n top: 40px;\n}\n</style>\n\n<div class=\"board-header\">\n \n <h1 class=\"board-title\"> 有什么想说的...</h1>\n \n \n <div class=\"welcome-text\">\n <p> ✨ 好吃的<br>\n ✨ 好玩的 <br> \n ✨ 都来说说吧 </p>\n </div>\n</div>\n"},{"title":"友情链接","date":"2025-03-03T14:00:00.000Z","type":"link","comments":0,"_content":"","source":"link/index.md","raw":"---\ntitle: 友情链接\ndate: 2025-03-03 22:00:00\ntype: \"link\"\ncomments: false\n---\n","updated":"2025-03-05T07:05:28.831Z","path":"link/index.html","layout":"page","_id":"cmkmd8tyr0002cw64baa04e2z","content":"<link rel=\"stylesheet\" class=\"aplayer-secondary-style-marker\" href=\"\\assets\\css\\APlayer.min.css\"><script src=\"\\assets\\js\\APlayer.min.js\" class=\"aplayer-secondary-script-marker\"></script>","excerpt":"","more":""},{"title":"标签","date":"2025-03-04T03:51:48.000Z","type":"tags","orderby":"random","order":1,"comments":0,"_content":"","source":"tags/index.md","raw":"---\ntitle: 标签\ndate: 2025-03-04 11:51:48\ntype: \"tags\"\norderby: random\norder: 1\ncomments: false\n---\n","updated":"2025-03-05T07:05:39.369Z","path":"tags/index.html","layout":"page","_id":"cmkmd8tyt0005cw64hqct30gu","content":"<link rel=\"stylesheet\" class=\"aplayer-secondary-style-marker\" href=\"\\assets\\css\\APlayer.min.css\"><script src=\"\\assets\\js\\APlayer.min.js\" class=\"aplayer-secondary-script-marker\"></script>","excerpt":"","more":""}],"Post":[{"title":"初试C++ 1.0","top_img":"transparent","comments":0,"_content":"\n# 初学 C++\n\n---\n\n## io 流--输入/输出操作符\n\n### 标头< iostream >\n\n•**endl**,输出 '\\n' 并冲洗输出流。例如:cout << endl;\n\n•**dec, hex, oct**,更改用于整数输入/输出的基数(进制)\n\n•**left,right**, 设置填充字符的布置,即左对齐或右对齐\n\n•**fixed,scientific**,更改用于浮点 I/O 的格式化\n\n•**showpoint,noshowpoint**,控制浮点表示是否始终包含小数点\n\n•**showpos,noshowpos**,控制是否将 + 号与非负数一同使用\n\n### 标头< iomanip >\n\n• setw(n),更改下个输入/输出域的宽度,宽度为 n\n\n• setprecision(n),更改浮点精度\n\n### 代码示例\n\n```cpp\n/* iostream-format.cpp */\n#include<iostream>\n#include<iomanip>\nusing namespace std;\nint main() {\ndouble myFloat=123.4578;\nint myInt=5;\ncout << fixed << showpoint << setprecision(3);\ncout << setw(10) << left << \"Float\";\ncout << setw(12) << right << myFloat << endl;\ncout << setw(10) << left << \"Int\";\ncout << setw(12) << right << myInt << endl;\nreturn 0;\n}\n```\n\n---\n\n## 命名空间\n\nC++命名空间提供了一种**避免名字冲突的方法**\n\n• 在命名空间块内声明的符号被放入一个**具名的作用域中**,避免这些符号被误认为其他作用域中的同名符号。\n\n• 多个命名空间块的名字<font color=aqua>**可以相同**,**这些块中的所有声明在该具名作用域声明**。</font>\n\n• 例如:标准库中符号(类型、变量、常量、函数等)都在 std 名命空间块中声明。cout 在 std 名命空间块中声明,则 std::cout 则是该变量的有限定名\n\n• **“::”是作用域解析运算符。**\n\n### 声明与使用\n\n#### 语法\n\n**namespace 命名空间名 { 声明序列 }**\n\n**• 声明具名命名空间**\n\n<font color=blue>using namespace 命名空间名 ;</font> \n<font color=blue>using 命名空间名 :: 成员名 ;</font>\n\n### 名命冲突示例\n\n```cpp\n/* ns-helloworld.cpp */\n#include<iostream>\nusing namespace std;\nint main() {\nconst char *cout = \"hello world c++!\";\nstd::cout << cout << endl;\nreturn 0;\n}\n```\n\nstd::cout 是标准输出流对象**有限定名称**,避免了字符串变量 cout 的命名冲突\n\n### 嵌套示例\n\n```cpp\n/* ns-embed.cpp */\n#include<iostream>\nusing namespace std;\nnamespace sysu {\n namespace students {\n int collegeCount;\n void printColleges();\n }\n}\n\nvoid sysu::students::printColleges() {\ncout << \"Colleges \" << collegeCount << endl;\n}\n\nint main() {\nusing namespace sysu::students;\ncollegeCount = 23;\nprintColleges();\nreturn 0;\n}\n```\n\n---\n\n## 引用\n\n### 引用的概念\n\n• 声明具名的变量引用,即既存对象或函数的别名。\n\n• 引用名**特点**:使用时类似变量,作为参数时能传引用\n\n### 左值声明与示例\n\n左值引用的**申明**:**type &别名 [= 左值表达式]**\n\n```cpp\n/* ref-definition.cpp */\n#include<iostream>\nusing namespace std;\nint main() {\nint a = 1024;\nint *p = &a; // p是指针; &a是a的地址\n int &x = a; // x是引用,它实际上与a是同一个变量\n cout << \"a = \" << a << endl;\ncout << \"x = \" << x << endl;\ncout << \"*p = \" << *p << endl;\nx = 2000;\ncout << \"a = \" << a << endl;\nreturn 0;\n}\n```\n\n### 注意\n\n**引用不是对象**。它们可以不占用存储,尽管若需要分配存储以实现所需语义(例如,引用类型的非静态数\n\n据成员通常会增加类的大小,量为存储内存地址所需),则由编译器具体实现决定。\n\n**因为引用不是对象**,故\n\n<font color=red>**• 不存在引用的数组**\n\n**• 不存在指向引用的指针**\n\n**• 不存在引用的引用**\n\n**• C++不存在引用为空的概念,即引用必须被定义**</font>\n\n### 指针与引用\n\n• **相同**:可以使一个函数向调用者返回多个数值。\n\n• **不同**:原理不同。引用作为函数参数,<font color=blue>**实参是变量本身,形参是实参变量的别名**</font>,使用变量时不需要解引用。而指针作函数参数,则实参是某变量的地址,使用这个地址访问对应的变量必须解引用。指针可以是 null 值,引用不可以是 null 值。\n\n• 从返回值的角度看,**引用形参比利用指针方便**。\n\n---\n\n# 理论题\n\n## 1\n\n```cpp\n下述语句的输出是:\n\ncout << 1 + \"20.24\" << endl << 20.24;\n```\n\n**<font color=blue>1 + \"20.24\" </font>**\n\n\"20.24\" 是字符串字面量,类型为 const char\\*,指向字符 '2' 的地址。\n\n1 + \"20.24\" 是对指针的算术运算。指针加 1 会移动 sizeof(char)(即 1 字节),因此指向字符串的第二个字符 '0'。\n\n此时,指针指向的子字符串为 \"0.24\",cout 会从该位置开始输出,直到遇到终止符 \\0,故输出 0.24。\n\n## 2\n\n**<font color=blue>所有同名命名空间块的内容会被合并到同一命名空间</font>**\n\n### 3\n\n```cpp\n以下代码的输出结果是什么?\n\ncout << fixed << 3.14159 << endl;\n\n3.141590\n```\n\nstd::fixed 是 C++ 中的流操纵符,用于强制浮点数以固定小数格式输出,而非科学计数法。当未指定精度时,**默认保留 6 位小数**,不足的位数会自动补零\n\n**<font color=red>若需控制小数点后的位数,需结合 setprecision(n)</font>**\n\n例:\n\n```cpp\ncout << fixed << setprecision(2) << 3.14159 << endl;\n```\n","source":"_posts/first-blog.md","raw":"---\ntitle: 初试C++ 1.0\ntags: C++\ntop_img: transparent\ncomments: false\n---\n\n# 初学 C++\n\n---\n\n## io 流--输入/输出操作符\n\n### 标头< iostream >\n\n•**endl**,输出 '\\n' 并冲洗输出流。例如:cout << endl;\n\n•**dec, hex, oct**,更改用于整数输入/输出的基数(进制)\n\n•**left,right**, 设置填充字符的布置,即左对齐或右对齐\n\n•**fixed,scientific**,更改用于浮点 I/O 的格式化\n\n•**showpoint,noshowpoint**,控制浮点表示是否始终包含小数点\n\n•**showpos,noshowpos**,控制是否将 + 号与非负数一同使用\n\n### 标头< iomanip >\n\n• setw(n),更改下个输入/输出域的宽度,宽度为 n\n\n• setprecision(n),更改浮点精度\n\n### 代码示例\n\n```cpp\n/* iostream-format.cpp */\n#include<iostream>\n#include<iomanip>\nusing namespace std;\nint main() {\ndouble myFloat=123.4578;\nint myInt=5;\ncout << fixed << showpoint << setprecision(3);\ncout << setw(10) << left << \"Float\";\ncout << setw(12) << right << myFloat << endl;\ncout << setw(10) << left << \"Int\";\ncout << setw(12) << right << myInt << endl;\nreturn 0;\n}\n```\n\n---\n\n## 命名空间\n\nC++命名空间提供了一种**避免名字冲突的方法**\n\n• 在命名空间块内声明的符号被放入一个**具名的作用域中**,避免这些符号被误认为其他作用域中的同名符号。\n\n• 多个命名空间块的名字<font color=aqua>**可以相同**,**这些块中的所有声明在该具名作用域声明**。</font>\n\n• 例如:标准库中符号(类型、变量、常量、函数等)都在 std 名命空间块中声明。cout 在 std 名命空间块中声明,则 std::cout 则是该变量的有限定名\n\n• **“::”是作用域解析运算符。**\n\n### 声明与使用\n\n#### 语法\n\n**namespace 命名空间名 { 声明序列 }**\n\n**• 声明具名命名空间**\n\n<font color=blue>using namespace 命名空间名 ;</font> \n<font color=blue>using 命名空间名 :: 成员名 ;</font>\n\n### 名命冲突示例\n\n```cpp\n/* ns-helloworld.cpp */\n#include<iostream>\nusing namespace std;\nint main() {\nconst char *cout = \"hello world c++!\";\nstd::cout << cout << endl;\nreturn 0;\n}\n```\n\nstd::cout 是标准输出流对象**有限定名称**,避免了字符串变量 cout 的命名冲突\n\n### 嵌套示例\n\n```cpp\n/* ns-embed.cpp */\n#include<iostream>\nusing namespace std;\nnamespace sysu {\n namespace students {\n int collegeCount;\n void printColleges();\n }\n}\n\nvoid sysu::students::printColleges() {\ncout << \"Colleges \" << collegeCount << endl;\n}\n\nint main() {\nusing namespace sysu::students;\ncollegeCount = 23;\nprintColleges();\nreturn 0;\n}\n```\n\n---\n\n## 引用\n\n### 引用的概念\n\n• 声明具名的变量引用,即既存对象或函数的别名。\n\n• 引用名**特点**:使用时类似变量,作为参数时能传引用\n\n### 左值声明与示例\n\n左值引用的**申明**:**type &别名 [= 左值表达式]**\n\n```cpp\n/* ref-definition.cpp */\n#include<iostream>\nusing namespace std;\nint main() {\nint a = 1024;\nint *p = &a; // p是指针; &a是a的地址\n int &x = a; // x是引用,它实际上与a是同一个变量\n cout << \"a = \" << a << endl;\ncout << \"x = \" << x << endl;\ncout << \"*p = \" << *p << endl;\nx = 2000;\ncout << \"a = \" << a << endl;\nreturn 0;\n}\n```\n\n### 注意\n\n**引用不是对象**。它们可以不占用存储,尽管若需要分配存储以实现所需语义(例如,引用类型的非静态数\n\n据成员通常会增加类的大小,量为存储内存地址所需),则由编译器具体实现决定。\n\n**因为引用不是对象**,故\n\n<font color=red>**• 不存在引用的数组**\n\n**• 不存在指向引用的指针**\n\n**• 不存在引用的引用**\n\n**• C++不存在引用为空的概念,即引用必须被定义**</font>\n\n### 指针与引用\n\n• **相同**:可以使一个函数向调用者返回多个数值。\n\n• **不同**:原理不同。引用作为函数参数,<font color=blue>**实参是变量本身,形参是实参变量的别名**</font>,使用变量时不需要解引用。而指针作函数参数,则实参是某变量的地址,使用这个地址访问对应的变量必须解引用。指针可以是 null 值,引用不可以是 null 值。\n\n• 从返回值的角度看,**引用形参比利用指针方便**。\n\n---\n\n# 理论题\n\n## 1\n\n```cpp\n下述语句的输出是:\n\ncout << 1 + \"20.24\" << endl << 20.24;\n```\n\n**<font color=blue>1 + \"20.24\" </font>**\n\n\"20.24\" 是字符串字面量,类型为 const char\\*,指向字符 '2' 的地址。\n\n1 + \"20.24\" 是对指针的算术运算。指针加 1 会移动 sizeof(char)(即 1 字节),因此指向字符串的第二个字符 '0'。\n\n此时,指针指向的子字符串为 \"0.24\",cout 会从该位置开始输出,直到遇到终止符 \\0,故输出 0.24。\n\n## 2\n\n**<font color=blue>所有同名命名空间块的内容会被合并到同一命名空间</font>**\n\n### 3\n\n```cpp\n以下代码的输出结果是什么?\n\ncout << fixed << 3.14159 << endl;\n\n3.141590\n```\n\nstd::fixed 是 C++ 中的流操纵符,用于强制浮点数以固定小数格式输出,而非科学计数法。当未指定精度时,**默认保留 6 位小数**,不足的位数会自动补零\n\n**<font color=red>若需控制小数点后的位数,需结合 setprecision(n)</font>**\n\n例:\n\n```cpp\ncout << fixed << setprecision(2) << 3.14159 << endl;\n```\n","slug":"first-blog","published":1,"date":"2025-02-24T13:14:06.872Z","updated":"2025-03-05T11:59:31.930Z","layout":"post","photos":[],"_id":"cmkmd8typ0001cw64fa02ben6","content":"<link rel=\"stylesheet\" class=\"aplayer-secondary-style-marker\" href=\"\\assets\\css\\APlayer.min.css\"><script src=\"\\assets\\js\\APlayer.min.js\" class=\"aplayer-secondary-script-marker\"></script><h1 id=\"初学-C\"><a href=\"#初学-C\" class=\"headerlink\" title=\"初学 C++\"></a>初学 C++</h1><hr>\n<h2 id=\"io-流–输入-输出操作符\"><a href=\"#io-流–输入-输出操作符\" class=\"headerlink\" title=\"io 流–输入/输出操作符\"></a>io 流–输入/输出操作符</h2><h3 id=\"标头-iostream\"><a href=\"#标头-iostream\" class=\"headerlink\" title=\"标头< iostream >\"></a>标头< iostream ></h3><p>•<strong>endl</strong>,输出 ‘\\n’ 并冲洗输出流。例如:cout << endl;</p>\n<p>•<strong>dec, hex, oct</strong>,更改用于整数输入/输出的基数(进制)</p>\n<p>•<strong>left,right</strong>, 设置填充字符的布置,即左对齐或右对齐</p>\n<p>•<strong>fixed,scientific</strong>,更改用于浮点 I/O 的格式化</p>\n<p>•<strong>showpoint,noshowpoint</strong>,控制浮点表示是否始终包含小数点</p>\n<p>•<strong>showpos,noshowpos</strong>,控制是否将 + 号与非负数一同使用</p>\n<h3 id=\"标头-iomanip\"><a href=\"#标头-iomanip\" class=\"headerlink\" title=\"标头< iomanip >\"></a>标头< iomanip ></h3><p>• setw(n),更改下个输入/输出域的宽度,宽度为 n</p>\n<p>• setprecision(n),更改浮点精度</p>\n<h3 id=\"代码示例\"><a href=\"#代码示例\" class=\"headerlink\" title=\"代码示例\"></a>代码示例</h3><figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">/* iostream-format.cpp */</span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span><span class=\"string\"><iostream></span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span><span class=\"string\"><iomanip></span></span></span><br><span class=\"line\"><span class=\"keyword\">using</span> <span class=\"keyword\">namespace</span> std;</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span><span class=\"params\">()</span> </span>{</span><br><span class=\"line\"><span class=\"type\">double</span> myFloat=<span class=\"number\">123.4578</span>;</span><br><span class=\"line\"><span class=\"type\">int</span> myInt=<span class=\"number\">5</span>;</span><br><span class=\"line\">cout << fixed << showpoint << <span class=\"built_in\">setprecision</span>(<span class=\"number\">3</span>);</span><br><span class=\"line\">cout << <span class=\"built_in\">setw</span>(<span class=\"number\">10</span>) << left << <span class=\"string\">"Float"</span>;</span><br><span class=\"line\">cout << <span class=\"built_in\">setw</span>(<span class=\"number\">12</span>) << right << myFloat << endl;</span><br><span class=\"line\">cout << <span class=\"built_in\">setw</span>(<span class=\"number\">10</span>) << left << <span class=\"string\">"Int"</span>;</span><br><span class=\"line\">cout << <span class=\"built_in\">setw</span>(<span class=\"number\">12</span>) << right << myInt << endl;</span><br><span class=\"line\"><span class=\"keyword\">return</span> <span class=\"number\">0</span>;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<hr>\n<h2 id=\"命名空间\"><a href=\"#命名空间\" class=\"headerlink\" title=\"命名空间\"></a>命名空间</h2><p>C++命名空间提供了一种<strong>避免名字冲突的方法</strong></p>\n<p>• 在命名空间块内声明的符号被放入一个<strong>具名的作用域中</strong>,避免这些符号被误认为其他作用域中的同名符号。</p>\n<p>• 多个命名空间块的名字<font color=aqua><strong>可以相同</strong>,<strong>这些块中的所有声明在该具名作用域声明</strong>。</font></p>\n<p>• 例如:标准库中符号(类型、变量、常量、函数等)都在 std 名命空间块中声明。cout 在 std 名命空间块中声明,则 std::cout 则是该变量的有限定名</p>\n<p>• <strong>“::”是作用域解析运算符。</strong></p>\n<h3 id=\"声明与使用\"><a href=\"#声明与使用\" class=\"headerlink\" title=\"声明与使用\"></a>声明与使用</h3><h4 id=\"语法\"><a href=\"#语法\" class=\"headerlink\" title=\"语法\"></a>语法</h4><p><strong>namespace 命名空间名 { 声明序列 }</strong></p>\n<p><strong>• 声明具名命名空间</strong></p>\n<p><font color=blue>using namespace 命名空间名 ;</font><br><font color=blue>using 命名空间名 :: 成员名 ;</font></p>\n<h3 id=\"名命冲突示例\"><a href=\"#名命冲突示例\" class=\"headerlink\" title=\"名命冲突示例\"></a>名命冲突示例</h3><figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">/* ns-helloworld.cpp */</span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span><span class=\"string\"><iostream></span></span></span><br><span class=\"line\"><span class=\"keyword\">using</span> <span class=\"keyword\">namespace</span> std;</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span><span class=\"params\">()</span> </span>{</span><br><span class=\"line\"><span class=\"type\">const</span> <span class=\"type\">char</span> *cout = <span class=\"string\">"hello world c++!"</span>;</span><br><span class=\"line\">std::cout << cout << endl;</span><br><span class=\"line\"><span class=\"keyword\">return</span> <span class=\"number\">0</span>;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<p>std::cout 是标准输出流对象<strong>有限定名称</strong>,避免了字符串变量 cout 的命名冲突</p>\n<h3 id=\"嵌套示例\"><a href=\"#嵌套示例\" class=\"headerlink\" title=\"嵌套示例\"></a>嵌套示例</h3><figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">/* ns-embed.cpp */</span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span><span class=\"string\"><iostream></span></span></span><br><span class=\"line\"><span class=\"keyword\">using</span> <span class=\"keyword\">namespace</span> std;</span><br><span class=\"line\"><span class=\"keyword\">namespace</span> sysu {</span><br><span class=\"line\"> <span class=\"keyword\">namespace</span> students {</span><br><span class=\"line\"> <span class=\"type\">int</span> collegeCount;</span><br><span class=\"line\"> <span class=\"function\"><span class=\"type\">void</span> <span class=\"title\">printColleges</span><span class=\"params\">()</span></span>;</span><br><span class=\"line\"> }</span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"type\">void</span> sysu::students::<span class=\"built_in\">printColleges</span>() {</span><br><span class=\"line\">cout << <span class=\"string\">"Colleges "</span> << collegeCount << endl;</span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span><span class=\"params\">()</span> </span>{</span><br><span class=\"line\"><span class=\"keyword\">using</span> <span class=\"keyword\">namespace</span> sysu::students;</span><br><span class=\"line\">collegeCount = <span class=\"number\">23</span>;</span><br><span class=\"line\"><span class=\"built_in\">printColleges</span>();</span><br><span class=\"line\"><span class=\"keyword\">return</span> <span class=\"number\">0</span>;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<hr>\n<h2 id=\"引用\"><a href=\"#引用\" class=\"headerlink\" title=\"引用\"></a>引用</h2><h3 id=\"引用的概念\"><a href=\"#引用的概念\" class=\"headerlink\" title=\"引用的概念\"></a>引用的概念</h3><p>• 声明具名的变量引用,即既存对象或函数的别名。</p>\n<p>• 引用名<strong>特点</strong>:使用时类似变量,作为参数时能传引用</p>\n<h3 id=\"左值声明与示例\"><a href=\"#左值声明与示例\" class=\"headerlink\" title=\"左值声明与示例\"></a>左值声明与示例</h3><p>左值引用的<strong>申明</strong>:<strong>type &别名 [= 左值表达式]</strong></p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">/* ref-definition.cpp */</span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span><span class=\"string\"><iostream></span></span></span><br><span class=\"line\"><span class=\"keyword\">using</span> <span class=\"keyword\">namespace</span> std;</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span><span class=\"params\">()</span> </span>{</span><br><span class=\"line\"><span class=\"type\">int</span> a = <span class=\"number\">1024</span>;</span><br><span class=\"line\"><span class=\"type\">int</span> *p = &a; <span class=\"comment\">// p是指针; &a是a的地址</span></span><br><span class=\"line\"> <span class=\"type\">int</span> &x = a; <span class=\"comment\">// x是引用,它实际上与a是同一个变量</span></span><br><span class=\"line\"> cout << <span class=\"string\">"a = "</span> << a << endl;</span><br><span class=\"line\">cout << <span class=\"string\">"x = "</span> << x << endl;</span><br><span class=\"line\">cout << <span class=\"string\">"*p = "</span> << *p << endl;</span><br><span class=\"line\">x = <span class=\"number\">2000</span>;</span><br><span class=\"line\">cout << <span class=\"string\">"a = "</span> << a << endl;</span><br><span class=\"line\"><span class=\"keyword\">return</span> <span class=\"number\">0</span>;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<h3 id=\"注意\"><a href=\"#注意\" class=\"headerlink\" title=\"注意\"></a>注意</h3><p><strong>引用不是对象</strong>。它们可以不占用存储,尽管若需要分配存储以实现所需语义(例如,引用类型的非静态数</p>\n<p>据成员通常会增加类的大小,量为存储内存地址所需),则由编译器具体实现决定。</p>\n<p><strong>因为引用不是对象</strong>,故</p>\n<p><font color=red><strong>• 不存在引用的数组</strong></p>\n<p><strong>• 不存在指向引用的指针</strong></p>\n<p><strong>• 不存在引用的引用</strong></p>\n<p><strong>• C++不存在引用为空的概念,即引用必须被定义</strong></font></p>\n<h3 id=\"指针与引用\"><a href=\"#指针与引用\" class=\"headerlink\" title=\"指针与引用\"></a>指针与引用</h3><p>• <strong>相同</strong>:可以使一个函数向调用者返回多个数值。</p>\n<p>• <strong>不同</strong>:原理不同。引用作为函数参数,<font color=blue><strong>实参是变量本身,形参是实参变量的别名</strong></font>,使用变量时不需要解引用。而指针作函数参数,则实参是某变量的地址,使用这个地址访问对应的变量必须解引用。指针可以是 null 值,引用不可以是 null 值。</p>\n<p>• 从返回值的角度看,<strong>引用形参比利用指针方便</strong>。</p>\n<hr>\n<h1 id=\"理论题\"><a href=\"#理论题\" class=\"headerlink\" title=\"理论题\"></a>理论题</h1><h2 id=\"1\"><a href=\"#1\" class=\"headerlink\" title=\"1\"></a>1</h2><figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\">下述语句的输出是:</span><br><span class=\"line\"></span><br><span class=\"line\">cout << <span class=\"number\">1</span> + <span class=\"string\">"20.24"</span> << endl << <span class=\"number\">20.24</span>;</span><br></pre></td></tr></table></figure>\n\n<p><strong><font color=blue>1 + “20.24” </font></strong></p>\n<p>“20.24” 是字符串字面量,类型为 const char*,指向字符 ‘2’ 的地址。</p>\n<p>1 + “20.24” 是对指针的算术运算。指针加 1 会移动 sizeof(char)(即 1 字节),因此指向字符串的第二个字符 ‘0’。</p>\n<p>此时,指针指向的子字符串为 “0.24”,cout 会从该位置开始输出,直到遇到终止符 \\0,故输出 0.24。</p>\n<h2 id=\"2\"><a href=\"#2\" class=\"headerlink\" title=\"2\"></a>2</h2><p><strong><font color=blue>所有同名命名空间块的内容会被合并到同一命名空间</font></strong></p>\n<h3 id=\"3\"><a href=\"#3\" class=\"headerlink\" title=\"3\"></a>3</h3><figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\">以下代码的输出结果是什么?</span><br><span class=\"line\"></span><br><span class=\"line\">cout << fixed << <span class=\"number\">3.14159</span> << endl;</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"number\">3.141590</span></span><br></pre></td></tr></table></figure>\n\n<p>std::fixed 是 C++ 中的流操纵符,用于强制浮点数以固定小数格式输出,而非科学计数法。当未指定精度时,<strong>默认保留 6 位小数</strong>,不足的位数会自动补零</p>\n<p><strong><font color=red>若需控制小数点后的位数,需结合 setprecision(n)</font></strong></p>\n<p>例:</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\">cout << fixed << <span class=\"built_in\">setprecision</span>(<span class=\"number\">2</span>) << <span class=\"number\">3.14159</span> << endl;</span><br></pre></td></tr></table></figure>\n","excerpt":"","more":"<h1 id=\"初学-C\"><a href=\"#初学-C\" class=\"headerlink\" title=\"初学 C++\"></a>初学 C++</h1><hr>\n<h2 id=\"io-流–输入-输出操作符\"><a href=\"#io-流–输入-输出操作符\" class=\"headerlink\" title=\"io 流–输入/输出操作符\"></a>io 流–输入/输出操作符</h2><h3 id=\"标头-iostream\"><a href=\"#标头-iostream\" class=\"headerlink\" title=\"标头< iostream >\"></a>标头< iostream ></h3><p>•<strong>endl</strong>,输出 ‘\\n’ 并冲洗输出流。例如:cout << endl;</p>\n<p>•<strong>dec, hex, oct</strong>,更改用于整数输入/输出的基数(进制)</p>\n<p>•<strong>left,right</strong>, 设置填充字符的布置,即左对齐或右对齐</p>\n<p>•<strong>fixed,scientific</strong>,更改用于浮点 I/O 的格式化</p>\n<p>•<strong>showpoint,noshowpoint</strong>,控制浮点表示是否始终包含小数点</p>\n<p>•<strong>showpos,noshowpos</strong>,控制是否将 + 号与非负数一同使用</p>\n<h3 id=\"标头-iomanip\"><a href=\"#标头-iomanip\" class=\"headerlink\" title=\"标头< iomanip >\"></a>标头< iomanip ></h3><p>• setw(n),更改下个输入/输出域的宽度,宽度为 n</p>\n<p>• setprecision(n),更改浮点精度</p>\n<h3 id=\"代码示例\"><a href=\"#代码示例\" class=\"headerlink\" title=\"代码示例\"></a>代码示例</h3><figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">/* iostream-format.cpp */</span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span><span class=\"string\"><iostream></span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span><span class=\"string\"><iomanip></span></span></span><br><span class=\"line\"><span class=\"keyword\">using</span> <span class=\"keyword\">namespace</span> std;</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span><span class=\"params\">()</span> </span>{</span><br><span class=\"line\"><span class=\"type\">double</span> myFloat=<span class=\"number\">123.4578</span>;</span><br><span class=\"line\"><span class=\"type\">int</span> myInt=<span class=\"number\">5</span>;</span><br><span class=\"line\">cout << fixed << showpoint << <span class=\"built_in\">setprecision</span>(<span class=\"number\">3</span>);</span><br><span class=\"line\">cout << <span class=\"built_in\">setw</span>(<span class=\"number\">10</span>) << left << <span class=\"string\">"Float"</span>;</span><br><span class=\"line\">cout << <span class=\"built_in\">setw</span>(<span class=\"number\">12</span>) << right << myFloat << endl;</span><br><span class=\"line\">cout << <span class=\"built_in\">setw</span>(<span class=\"number\">10</span>) << left << <span class=\"string\">"Int"</span>;</span><br><span class=\"line\">cout << <span class=\"built_in\">setw</span>(<span class=\"number\">12</span>) << right << myInt << endl;</span><br><span class=\"line\"><span class=\"keyword\">return</span> <span class=\"number\">0</span>;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<hr>\n<h2 id=\"命名空间\"><a href=\"#命名空间\" class=\"headerlink\" title=\"命名空间\"></a>命名空间</h2><p>C++命名空间提供了一种<strong>避免名字冲突的方法</strong></p>\n<p>• 在命名空间块内声明的符号被放入一个<strong>具名的作用域中</strong>,避免这些符号被误认为其他作用域中的同名符号。</p>\n<p>• 多个命名空间块的名字<font color=aqua><strong>可以相同</strong>,<strong>这些块中的所有声明在该具名作用域声明</strong>。</font></p>\n<p>• 例如:标准库中符号(类型、变量、常量、函数等)都在 std 名命空间块中声明。cout 在 std 名命空间块中声明,则 std::cout 则是该变量的有限定名</p>\n<p>• <strong>“::”是作用域解析运算符。</strong></p>\n<h3 id=\"声明与使用\"><a href=\"#声明与使用\" class=\"headerlink\" title=\"声明与使用\"></a>声明与使用</h3><h4 id=\"语法\"><a href=\"#语法\" class=\"headerlink\" title=\"语法\"></a>语法</h4><p><strong>namespace 命名空间名 { 声明序列 }</strong></p>\n<p><strong>• 声明具名命名空间</strong></p>\n<p><font color=blue>using namespace 命名空间名 ;</font><br><font color=blue>using 命名空间名 :: 成员名 ;</font></p>\n<h3 id=\"名命冲突示例\"><a href=\"#名命冲突示例\" class=\"headerlink\" title=\"名命冲突示例\"></a>名命冲突示例</h3><figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">/* ns-helloworld.cpp */</span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span><span class=\"string\"><iostream></span></span></span><br><span class=\"line\"><span class=\"keyword\">using</span> <span class=\"keyword\">namespace</span> std;</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span><span class=\"params\">()</span> </span>{</span><br><span class=\"line\"><span class=\"type\">const</span> <span class=\"type\">char</span> *cout = <span class=\"string\">"hello world c++!"</span>;</span><br><span class=\"line\">std::cout << cout << endl;</span><br><span class=\"line\"><span class=\"keyword\">return</span> <span class=\"number\">0</span>;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<p>std::cout 是标准输出流对象<strong>有限定名称</strong>,避免了字符串变量 cout 的命名冲突</p>\n<h3 id=\"嵌套示例\"><a href=\"#嵌套示例\" class=\"headerlink\" title=\"嵌套示例\"></a>嵌套示例</h3><figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">/* ns-embed.cpp */</span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span><span class=\"string\"><iostream></span></span></span><br><span class=\"line\"><span class=\"keyword\">using</span> <span class=\"keyword\">namespace</span> std;</span><br><span class=\"line\"><span class=\"keyword\">namespace</span> sysu {</span><br><span class=\"line\"> <span class=\"keyword\">namespace</span> students {</span><br><span class=\"line\"> <span class=\"type\">int</span> collegeCount;</span><br><span class=\"line\"> <span class=\"function\"><span class=\"type\">void</span> <span class=\"title\">printColleges</span><span class=\"params\">()</span></span>;</span><br><span class=\"line\"> }</span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"type\">void</span> sysu::students::<span class=\"built_in\">printColleges</span>() {</span><br><span class=\"line\">cout << <span class=\"string\">"Colleges "</span> << collegeCount << endl;</span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span><span class=\"params\">()</span> </span>{</span><br><span class=\"line\"><span class=\"keyword\">using</span> <span class=\"keyword\">namespace</span> sysu::students;</span><br><span class=\"line\">collegeCount = <span class=\"number\">23</span>;</span><br><span class=\"line\"><span class=\"built_in\">printColleges</span>();</span><br><span class=\"line\"><span class=\"keyword\">return</span> <span class=\"number\">0</span>;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<hr>\n<h2 id=\"引用\"><a href=\"#引用\" class=\"headerlink\" title=\"引用\"></a>引用</h2><h3 id=\"引用的概念\"><a href=\"#引用的概念\" class=\"headerlink\" title=\"引用的概念\"></a>引用的概念</h3><p>• 声明具名的变量引用,即既存对象或函数的别名。</p>\n<p>• 引用名<strong>特点</strong>:使用时类似变量,作为参数时能传引用</p>\n<h3 id=\"左值声明与示例\"><a href=\"#左值声明与示例\" class=\"headerlink\" title=\"左值声明与示例\"></a>左值声明与示例</h3><p>左值引用的<strong>申明</strong>:<strong>type &别名 [= 左值表达式]</strong></p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">/* ref-definition.cpp */</span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span><span class=\"string\"><iostream></span></span></span><br><span class=\"line\"><span class=\"keyword\">using</span> <span class=\"keyword\">namespace</span> std;</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span><span class=\"params\">()</span> </span>{</span><br><span class=\"line\"><span class=\"type\">int</span> a = <span class=\"number\">1024</span>;</span><br><span class=\"line\"><span class=\"type\">int</span> *p = &a; <span class=\"comment\">// p是指针; &a是a的地址</span></span><br><span class=\"line\"> <span class=\"type\">int</span> &x = a; <span class=\"comment\">// x是引用,它实际上与a是同一个变量</span></span><br><span class=\"line\"> cout << <span class=\"string\">"a = "</span> << a << endl;</span><br><span class=\"line\">cout << <span class=\"string\">"x = "</span> << x << endl;</span><br><span class=\"line\">cout << <span class=\"string\">"*p = "</span> << *p << endl;</span><br><span class=\"line\">x = <span class=\"number\">2000</span>;</span><br><span class=\"line\">cout << <span class=\"string\">"a = "</span> << a << endl;</span><br><span class=\"line\"><span class=\"keyword\">return</span> <span class=\"number\">0</span>;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<h3 id=\"注意\"><a href=\"#注意\" class=\"headerlink\" title=\"注意\"></a>注意</h3><p><strong>引用不是对象</strong>。它们可以不占用存储,尽管若需要分配存储以实现所需语义(例如,引用类型的非静态数</p>\n<p>据成员通常会增加类的大小,量为存储内存地址所需),则由编译器具体实现决定。</p>\n<p><strong>因为引用不是对象</strong>,故</p>\n<p><font color=red><strong>• 不存在引用的数组</strong></p>\n<p><strong>• 不存在指向引用的指针</strong></p>\n<p><strong>• 不存在引用的引用</strong></p>\n<p><strong>• C++不存在引用为空的概念,即引用必须被定义</strong></font></p>\n<h3 id=\"指针与引用\"><a href=\"#指针与引用\" class=\"headerlink\" title=\"指针与引用\"></a>指针与引用</h3><p>• <strong>相同</strong>:可以使一个函数向调用者返回多个数值。</p>\n<p>• <strong>不同</strong>:原理不同。引用作为函数参数,<font color=blue><strong>实参是变量本身,形参是实参变量的别名</strong></font>,使用变量时不需要解引用。而指针作函数参数,则实参是某变量的地址,使用这个地址访问对应的变量必须解引用。指针可以是 null 值,引用不可以是 null 值。</p>\n<p>• 从返回值的角度看,<strong>引用形参比利用指针方便</strong>。</p>\n<hr>\n<h1 id=\"理论题\"><a href=\"#理论题\" class=\"headerlink\" title=\"理论题\"></a>理论题</h1><h2 id=\"1\"><a href=\"#1\" class=\"headerlink\" title=\"1\"></a>1</h2><figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\">下述语句的输出是:</span><br><span class=\"line\"></span><br><span class=\"line\">cout << <span class=\"number\">1</span> + <span class=\"string\">"20.24"</span> << endl << <span class=\"number\">20.24</span>;</span><br></pre></td></tr></table></figure>\n\n<p><strong><font color=blue>1 + “20.24” </font></strong></p>\n<p>“20.24” 是字符串字面量,类型为 const char*,指向字符 ‘2’ 的地址。</p>\n<p>1 + “20.24” 是对指针的算术运算。指针加 1 会移动 sizeof(char)(即 1 字节),因此指向字符串的第二个字符 ‘0’。</p>\n<p>此时,指针指向的子字符串为 “0.24”,cout 会从该位置开始输出,直到遇到终止符 \\0,故输出 0.24。</p>\n<h2 id=\"2\"><a href=\"#2\" class=\"headerlink\" title=\"2\"></a>2</h2><p><strong><font color=blue>所有同名命名空间块的内容会被合并到同一命名空间</font></strong></p>\n<h3 id=\"3\"><a href=\"#3\" class=\"headerlink\" title=\"3\"></a>3</h3><figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\">以下代码的输出结果是什么?</span><br><span class=\"line\"></span><br><span class=\"line\">cout << fixed << <span class=\"number\">3.14159</span> << endl;</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"number\">3.141590</span></span><br></pre></td></tr></table></figure>\n\n<p>std::fixed 是 C++ 中的流操纵符,用于强制浮点数以固定小数格式输出,而非科学计数法。当未指定精度时,<strong>默认保留 6 位小数</strong>,不足的位数会自动补零</p>\n<p><strong><font color=red>若需控制小数点后的位数,需结合 setprecision(n)</font></strong></p>\n<p>例:</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\">cout << fixed << <span class=\"built_in\">setprecision</span>(<span class=\"number\">2</span>) << <span class=\"number\">3.14159</span> << endl;</span><br></pre></td></tr></table></figure>\n"},{"title":"数据抽象和类II","top_img":"transparent","comments":0,"_content":"\n# 数据抽象和类 II\n\n## C 与 C++动态对象(变量)管理\n\n堆(Heap)\n• 共享的对象(变量)空间\n• 由 stdlib 库管理\n\n### C\n\n必须 #include <stdlib.h>\n• 申请空间,`void * malloc(size_t)`\n• 释放空间,`void free(void *)`\n\n```c\n#include<stdio.h>\n#include<stdlib.h>\ntypedef struct { int x; int y; } Point;\nint main() {\n// 分配变量或一维可变数组\nPoint *p1 = malloc(sizeof(Point) * 10);\n// 分配二维数组(n,m是常数)\nPoint (*p2)[2][3] = malloc(sizeof(Point) * 6);\n// 分配数组的数组\nint n = 2, m = 3;\nPoint **p3 = malloc(sizeof(Point *) * n);\nfor (size_t i = 0; i < n; i++){\np3[i] = malloc(sizeof(Point) * m);\n}\n// do somesthing\nfree(p1);\nfree(p2);\n// 必须先释放行数组\nfor (size_t i = 0; i < n; i++){\nfree(p3[i]);\n}\nfree(p3);\nreturn 0;\n}\n```\n\n### C++ 动态对象(变量)与对象指针\n\n<font color=red>**new 和 delete 运算符**</font>\n**new**\n• 分配空间\n• 每个对象调用构造器\n• 若内存分配失败,**抛出异常,不是 NULL**\n\n```\n指针=new 类型名;//动态创建一个对象\n指针=new 类型名(初始化参数);//动态创建一个对象并指定初始化参数\n指针=new 类型名[数组长度];//用于动态分配数组\n```\n\n**返回该类型的指针**\n注:不是万能指针 `void *`\n\n**delete []p**\n• 为数组每个对象析构\n• 释放空间\n\n```\ndelete 变量名;//基本用法\ndelete []变量名;//用于释放数组\n```\n\n如果动态分配了一个数组,但是却用 delete p 的方式释放,没有用[],则编译时\n没有问题,运行时可能不会发生错误,但实际上会导致动态分配的数组没有被完\n全释放。\n\n用 delete 释放空间后,指针的值仍是原来指向的地址,但指针已无效(重复释放\n将出错)\n\n例:\n\n```cpp\n#include<iostream>\nusing namespace std;\nvoid inc(int *p, int Length) {\nfor (int i = 0; i < Length; i++)\np[i]++;\n}\nint main() {\nint *p;\nint Length, i;\ncout << \"Enter the lenght you want: \";\ncin >> Length;\np = new int[Length]{1,3,5};\ninc(p, Length);\nfor (i = 0 ; i < Length; i++)\ncout << *(p+i) << \" \";\ndelete []p;\n}\n```\n\n#### 对象指针访问成员\n\n```cpp\nint main() {\nText* str_ptr;\nText str(\"on stack 1\");\nstr_ptr = &str;//取对象地址\nstr.Print(); //对象取成员\nstr_ptr->Print();//指针取成员\n}\n```\n\n## =delete 和 =default\n\n### 显式定义默认函数:=default\n\n当我们声明有参构造函数时,编译器不会创建默认构造函数。\n\n• =default 必须在函数申明后,让编译创建该构造函数\n\n**• 特殊成员函数包括:**\n➢ 默认构造函数:T()\n➢ 析构函数:~T()\n➢ 复制构造函数:T(const T&)\n➢ 赋值运算:operator=(const T&)\n➢ …\n\n• 函数不能再自定义实现\n例:\n\n```cpp\n#include <iostream>\nusing namespace std;\nclass A\n{\npublic:\nA(int x) {\ncout << \"This is a parameterized constructor\";\n}\nA() = default;\n};\nint main(){\nA a; //call A()\nA x(1); //call A(int x)\ncout<<endl;\nreturn 0;\n}\n```\n\n### 弃置函数:=delete\n\n任何弃置函数的使用都是非良构的(程序无法编译)\n\n删除的函数是隐式内联的,这一点非常重要,删除的函数定义必须是函数的**首次声明**\n\n```cpp\n例:\nclass A {\npublic:\nA(int x): m(x) { }\n// Delete the copy constructor\nA(const A&) = delete;\n// Delete the copy assignment operator\nA& operator=(const A&) = delete;\nint m;\n};\n\n以下方法是将函数声明为已删除的正确方法:\nclass C {\npublic:\nC(C& a) = delete;\n};\n但是以下尝试声明删除函数的方法会产生错误:\n// incorrect syntax of declaring a member function as deleted\nclass C {\npublic:\nC();\n};\n// Error, the deleted definition of function C must be the first declaration of the function.\nC::C() = delete;\n```\n\n## 对象成员初始化\n\n#### 默认成员初始化器\n\n它是成员声明中包含的花括号或等号初始化器\n\n#### 成员初始化器列表\n\n```cpp\nstruct Ray {\nRay (Vector3 origin, Vector3\ndirection):origin(origin),direction(direction) {};\nVector3 origin; //射线的原点。\nVector3 direction; //射线的方向。\n};\n```\n\n**必须使用初始化器列表的时候:**\n\n1.常量成员,因为常量只能初始化不能赋值,所以必须放在初始化器列表里面\n\n2.引用类型,引用必须在定义的时候初始化,并且不能重新赋值,所以也要使用初始化器\n\n3.没有无参构造函数的类成员,使用初始化器列表可以使用有参构造函数初始化\n\n成员是按照他们在类中声明的顺序进行初始化的,而不是按照他们在初始化器\n列表出现的顺序初始化的:\n\n```cpp\nclass foo {\npublic:\nint i ;int j ;\nfoo(int x):i(x), j(i){}; // ok, 先初始化i,后初始化j\n};\n```\n","source":"_posts/fith-blog.md","raw":"---\ntitle: 数据抽象和类II\ntags: C++\ntop_img: transparent\ncomments: false\n---\n\n# 数据抽象和类 II\n\n## C 与 C++动态对象(变量)管理\n\n堆(Heap)\n• 共享的对象(变量)空间\n• 由 stdlib 库管理\n\n### C\n\n必须 #include <stdlib.h>\n• 申请空间,`void * malloc(size_t)`\n• 释放空间,`void free(void *)`\n\n```c\n#include<stdio.h>\n#include<stdlib.h>\ntypedef struct { int x; int y; } Point;\nint main() {\n// 分配变量或一维可变数组\nPoint *p1 = malloc(sizeof(Point) * 10);\n// 分配二维数组(n,m是常数)\nPoint (*p2)[2][3] = malloc(sizeof(Point) * 6);\n// 分配数组的数组\nint n = 2, m = 3;\nPoint **p3 = malloc(sizeof(Point *) * n);\nfor (size_t i = 0; i < n; i++){\np3[i] = malloc(sizeof(Point) * m);\n}\n// do somesthing\nfree(p1);\nfree(p2);\n// 必须先释放行数组\nfor (size_t i = 0; i < n; i++){\nfree(p3[i]);\n}\nfree(p3);\nreturn 0;\n}\n```\n\n### C++ 动态对象(变量)与对象指针\n\n<font color=red>**new 和 delete 运算符**</font>\n**new**\n• 分配空间\n• 每个对象调用构造器\n• 若内存分配失败,**抛出异常,不是 NULL**\n\n```\n指针=new 类型名;//动态创建一个对象\n指针=new 类型名(初始化参数);//动态创建一个对象并指定初始化参数\n指针=new 类型名[数组长度];//用于动态分配数组\n```\n\n**返回该类型的指针**\n注:不是万能指针 `void *`\n\n**delete []p**\n• 为数组每个对象析构\n• 释放空间\n\n```\ndelete 变量名;//基本用法\ndelete []变量名;//用于释放数组\n```\n\n如果动态分配了一个数组,但是却用 delete p 的方式释放,没有用[],则编译时\n没有问题,运行时可能不会发生错误,但实际上会导致动态分配的数组没有被完\n全释放。\n\n用 delete 释放空间后,指针的值仍是原来指向的地址,但指针已无效(重复释放\n将出错)\n\n例:\n\n```cpp\n#include<iostream>\nusing namespace std;\nvoid inc(int *p, int Length) {\nfor (int i = 0; i < Length; i++)\np[i]++;\n}\nint main() {\nint *p;\nint Length, i;\ncout << \"Enter the lenght you want: \";\ncin >> Length;\np = new int[Length]{1,3,5};\ninc(p, Length);\nfor (i = 0 ; i < Length; i++)\ncout << *(p+i) << \" \";\ndelete []p;\n}\n```\n\n#### 对象指针访问成员\n\n```cpp\nint main() {\nText* str_ptr;\nText str(\"on stack 1\");\nstr_ptr = &str;//取对象地址\nstr.Print(); //对象取成员\nstr_ptr->Print();//指针取成员\n}\n```\n\n## =delete 和 =default\n\n### 显式定义默认函数:=default\n\n当我们声明有参构造函数时,编译器不会创建默认构造函数。\n\n• =default 必须在函数申明后,让编译创建该构造函数\n\n**• 特殊成员函数包括:**\n➢ 默认构造函数:T()\n➢ 析构函数:~T()\n➢ 复制构造函数:T(const T&)\n➢ 赋值运算:operator=(const T&)\n➢ …\n\n• 函数不能再自定义实现\n例:\n\n```cpp\n#include <iostream>\nusing namespace std;\nclass A\n{\npublic:\nA(int x) {\ncout << \"This is a parameterized constructor\";\n}\nA() = default;\n};\nint main(){\nA a; //call A()\nA x(1); //call A(int x)\ncout<<endl;\nreturn 0;\n}\n```\n\n### 弃置函数:=delete\n\n任何弃置函数的使用都是非良构的(程序无法编译)\n\n删除的函数是隐式内联的,这一点非常重要,删除的函数定义必须是函数的**首次声明**\n\n```cpp\n例:\nclass A {\npublic:\nA(int x): m(x) { }\n// Delete the copy constructor\nA(const A&) = delete;\n// Delete the copy assignment operator\nA& operator=(const A&) = delete;\nint m;\n};\n\n以下方法是将函数声明为已删除的正确方法:\nclass C {\npublic:\nC(C& a) = delete;\n};\n但是以下尝试声明删除函数的方法会产生错误:\n// incorrect syntax of declaring a member function as deleted\nclass C {\npublic:\nC();\n};\n// Error, the deleted definition of function C must be the first declaration of the function.\nC::C() = delete;\n```\n\n## 对象成员初始化\n\n#### 默认成员初始化器\n\n它是成员声明中包含的花括号或等号初始化器\n\n#### 成员初始化器列表\n\n```cpp\nstruct Ray {\nRay (Vector3 origin, Vector3\ndirection):origin(origin),direction(direction) {};\nVector3 origin; //射线的原点。\nVector3 direction; //射线的方向。\n};\n```\n\n**必须使用初始化器列表的时候:**\n\n1.常量成员,因为常量只能初始化不能赋值,所以必须放在初始化器列表里面\n\n2.引用类型,引用必须在定义的时候初始化,并且不能重新赋值,所以也要使用初始化器\n\n3.没有无参构造函数的类成员,使用初始化器列表可以使用有参构造函数初始化\n\n成员是按照他们在类中声明的顺序进行初始化的,而不是按照他们在初始化器\n列表出现的顺序初始化的:\n\n```cpp\nclass foo {\npublic:\nint i ;int j ;\nfoo(int x):i(x), j(i){}; // ok, 先初始化i,后初始化j\n};\n```\n","slug":"fith-blog","published":1,"date":"2025-03-29T08:00:54.512Z","updated":"2025-03-29T08:01:28.161Z","layout":"post","photos":[],"_id":"cmkmd8tyr0003cw645bw24z1q","content":"<link rel=\"stylesheet\" class=\"aplayer-secondary-style-marker\" href=\"\\assets\\css\\APlayer.min.css\"><script src=\"\\assets\\js\\APlayer.min.js\" class=\"aplayer-secondary-script-marker\"></script><h1 id=\"数据抽象和类-II\"><a href=\"#数据抽象和类-II\" class=\"headerlink\" title=\"数据抽象和类 II\"></a>数据抽象和类 II</h1><h2 id=\"C-与-C-动态对象(变量)管理\"><a href=\"#C-与-C-动态对象(变量)管理\" class=\"headerlink\" title=\"C 与 C++动态对象(变量)管理\"></a>C 与 C++动态对象(变量)管理</h2><p>堆(Heap)<br>• 共享的对象(变量)空间<br>• 由 stdlib 库管理</p>\n<h3 id=\"C\"><a href=\"#C\" class=\"headerlink\" title=\"C\"></a>C</h3><p>必须 #include <stdlib.h><br>• 申请空间,<code>void * malloc(size_t)</code><br>• 释放空间,<code>void free(void *)</code></p>\n<figure class=\"highlight c\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span><span class=\"string\"><stdio.h></span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span><span class=\"string\"><stdlib.h></span></span></span><br><span class=\"line\"><span class=\"keyword\">typedef</span> <span class=\"class\"><span class=\"keyword\">struct</span> {</span> <span class=\"type\">int</span> x; <span class=\"type\">int</span> y; } Point;</span><br><span class=\"line\"><span class=\"type\">int</span> <span class=\"title function_\">main</span><span class=\"params\">()</span> {</span><br><span class=\"line\"><span class=\"comment\">// 分配变量或一维可变数组</span></span><br><span class=\"line\">Point *p1 = <span class=\"built_in\">malloc</span>(<span class=\"keyword\">sizeof</span>(Point) * <span class=\"number\">10</span>);</span><br><span class=\"line\"><span class=\"comment\">// 分配二维数组(n,m是常数)</span></span><br><span class=\"line\">Point (*p2)[<span class=\"number\">2</span>][<span class=\"number\">3</span>] = <span class=\"built_in\">malloc</span>(<span class=\"keyword\">sizeof</span>(Point) * <span class=\"number\">6</span>);</span><br><span class=\"line\"><span class=\"comment\">// 分配数组的数组</span></span><br><span class=\"line\"><span class=\"type\">int</span> n = <span class=\"number\">2</span>, m = <span class=\"number\">3</span>;</span><br><span class=\"line\">Point **p3 = <span class=\"built_in\">malloc</span>(<span class=\"keyword\">sizeof</span>(Point *) * n);</span><br><span class=\"line\"><span class=\"keyword\">for</span> (<span class=\"type\">size_t</span> i = <span class=\"number\">0</span>; i < n; i++){</span><br><span class=\"line\">p3[i] = <span class=\"built_in\">malloc</span>(<span class=\"keyword\">sizeof</span>(Point) * m);</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"comment\">// do somesthing</span></span><br><span class=\"line\"><span class=\"built_in\">free</span>(p1);</span><br><span class=\"line\"><span class=\"built_in\">free</span>(p2);</span><br><span class=\"line\"><span class=\"comment\">// 必须先释放行数组</span></span><br><span class=\"line\"><span class=\"keyword\">for</span> (<span class=\"type\">size_t</span> i = <span class=\"number\">0</span>; i < n; i++){</span><br><span class=\"line\"><span class=\"built_in\">free</span>(p3[i]);</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"built_in\">free</span>(p3);</span><br><span class=\"line\"><span class=\"keyword\">return</span> <span class=\"number\">0</span>;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<h3 id=\"C-动态对象(变量)与对象指针\"><a href=\"#C-动态对象(变量)与对象指针\" class=\"headerlink\" title=\"C++ 动态对象(变量)与对象指针\"></a>C++ 动态对象(变量)与对象指针</h3><p><font color=red><strong>new 和 delete 运算符</strong></font><br><strong>new</strong><br>• 分配空间<br>• 每个对象调用构造器<br>• 若内存分配失败,<strong>抛出异常,不是 NULL</strong></p>\n<figure class=\"highlight actionscript\"><table><tr><td class=\"code\"><pre><span class=\"line\">指针=<span class=\"keyword\">new</span> 类型名;<span class=\"comment\">//动态创建一个对象</span></span><br><span class=\"line\">指针=<span class=\"keyword\">new</span> 类型名(初始化参数);<span class=\"comment\">//动态创建一个对象并指定初始化参数</span></span><br><span class=\"line\">指针=<span class=\"keyword\">new</span> 类型名[数组长度];<span class=\"comment\">//用于动态分配数组</span></span><br></pre></td></tr></table></figure>\n\n<p><strong>返回该类型的指针</strong><br>注:不是万能指针 <code>void *</code></p>\n<p><strong>delete []p</strong><br>• 为数组每个对象析构<br>• 释放空间</p>\n<figure class=\"highlight actionscript\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">delete</span> 变量名;<span class=\"comment\">//基本用法</span></span><br><span class=\"line\"><span class=\"keyword\">delete</span> []变量名;<span class=\"comment\">//用于释放数组</span></span><br></pre></td></tr></table></figure>\n\n<p>如果动态分配了一个数组,但是却用 delete p 的方式释放,没有用[],则编译时<br>没有问题,运行时可能不会发生错误,但实际上会导致动态分配的数组没有被完<br>全释放。</p>\n<p>用 delete 释放空间后,指针的值仍是原来指向的地址,但指针已无效(重复释放<br>将出错)</p>\n<p>例:</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span><span class=\"string\"><iostream></span></span></span><br><span class=\"line\"><span class=\"keyword\">using</span> <span class=\"keyword\">namespace</span> std;</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">void</span> <span class=\"title\">inc</span><span class=\"params\">(<span class=\"type\">int</span> *p, <span class=\"type\">int</span> Length)</span> </span>{</span><br><span class=\"line\"><span class=\"keyword\">for</span> (<span class=\"type\">int</span> i = <span class=\"number\">0</span>; i < Length; i++)</span><br><span class=\"line\">p[i]++;</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span><span class=\"params\">()</span> </span>{</span><br><span class=\"line\"><span class=\"type\">int</span> *p;</span><br><span class=\"line\"><span class=\"type\">int</span> Length, i;</span><br><span class=\"line\">cout << <span class=\"string\">"Enter the lenght you want: "</span>;</span><br><span class=\"line\">cin >> Length;</span><br><span class=\"line\">p = <span class=\"keyword\">new</span> <span class=\"type\">int</span>[Length]{<span class=\"number\">1</span>,<span class=\"number\">3</span>,<span class=\"number\">5</span>};</span><br><span class=\"line\"><span class=\"built_in\">inc</span>(p, Length);</span><br><span class=\"line\"><span class=\"keyword\">for</span> (i = <span class=\"number\">0</span> ; i < Length; i++)</span><br><span class=\"line\">cout << *(p+i) << <span class=\"string\">" "</span>;</span><br><span class=\"line\"><span class=\"keyword\">delete</span> []p;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<h4 id=\"对象指针访问成员\"><a href=\"#对象指针访问成员\" class=\"headerlink\" title=\"对象指针访问成员\"></a>对象指针访问成员</h4><figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span><span class=\"params\">()</span> </span>{</span><br><span class=\"line\">Text* str_ptr;</span><br><span class=\"line\"><span class=\"function\">Text <span class=\"title\">str</span><span class=\"params\">(<span class=\"string\">"on stack 1"</span>)</span></span>;</span><br><span class=\"line\">str_ptr = &str;<span class=\"comment\">//取对象地址</span></span><br><span class=\"line\">str.<span class=\"built_in\">Print</span>(); <span class=\"comment\">//对象取成员</span></span><br><span class=\"line\">str_ptr-><span class=\"built_in\">Print</span>();<span class=\"comment\">//指针取成员</span></span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<h2 id=\"delete-和-default\"><a href=\"#delete-和-default\" class=\"headerlink\" title=\"=delete 和 =default\"></a>=delete 和 =default</h2><h3 id=\"显式定义默认函数:-default\"><a href=\"#显式定义默认函数:-default\" class=\"headerlink\" title=\"显式定义默认函数:=default\"></a>显式定义默认函数:=default</h3><p>当我们声明有参构造函数时,编译器不会创建默认构造函数。</p>\n<p>• =default 必须在函数申明后,让编译创建该构造函数</p>\n<p><strong>• 特殊成员函数包括:</strong><br>➢ 默认构造函数:T()<br>➢ 析构函数:~T()<br>➢ 复制构造函数:T(const T&)<br>➢ 赋值运算:operator=(const T&)<br>➢ …</p>\n<p>• 函数不能再自定义实现<br>例:</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span> <span class=\"string\"><iostream></span></span></span><br><span class=\"line\"><span class=\"keyword\">using</span> <span class=\"keyword\">namespace</span> std;</span><br><span class=\"line\"><span class=\"keyword\">class</span> <span class=\"title class_\">A</span></span><br><span class=\"line\">{</span><br><span class=\"line\"><span class=\"keyword\">public</span>:</span><br><span class=\"line\"><span class=\"built_in\">A</span>(<span class=\"type\">int</span> x) {</span><br><span class=\"line\">cout << <span class=\"string\">"This is a parameterized constructor"</span>;</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"built_in\">A</span>() = <span class=\"keyword\">default</span>;</span><br><span class=\"line\">};</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span><span class=\"params\">()</span></span>{</span><br><span class=\"line\">A a; <span class=\"comment\">//call A()</span></span><br><span class=\"line\"><span class=\"function\">A <span class=\"title\">x</span><span class=\"params\">(<span class=\"number\">1</span>)</span></span>; <span class=\"comment\">//call A(int x)</span></span><br><span class=\"line\">cout<<endl;</span><br><span class=\"line\"><span class=\"keyword\">return</span> <span class=\"number\">0</span>;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<h3 id=\"弃置函数:-delete\"><a href=\"#弃置函数:-delete\" class=\"headerlink\" title=\"弃置函数:=delete\"></a>弃置函数:=delete</h3><p>任何弃置函数的使用都是非良构的(程序无法编译)</p>\n<p>删除的函数是隐式内联的,这一点非常重要,删除的函数定义必须是函数的<strong>首次声明</strong></p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\">例:</span><br><span class=\"line\"><span class=\"keyword\">class</span> <span class=\"title class_\">A</span> {</span><br><span class=\"line\"><span class=\"keyword\">public</span>:</span><br><span class=\"line\"><span class=\"built_in\">A</span>(<span class=\"type\">int</span> x): <span class=\"built_in\">m</span>(x) { }</span><br><span class=\"line\"><span class=\"comment\">// Delete the copy constructor</span></span><br><span class=\"line\"><span class=\"built_in\">A</span>(<span class=\"type\">const</span> A&) = <span class=\"keyword\">delete</span>;</span><br><span class=\"line\"><span class=\"comment\">// Delete the copy assignment operator</span></span><br><span class=\"line\">A& <span class=\"keyword\">operator</span>=(<span class=\"type\">const</span> A&) = <span class=\"keyword\">delete</span>;</span><br><span class=\"line\"><span class=\"type\">int</span> m;</span><br><span class=\"line\">};</span><br><span class=\"line\"></span><br><span class=\"line\">以下方法是将函数声明为已删除的正确方法:</span><br><span class=\"line\"><span class=\"keyword\">class</span> <span class=\"title class_\">C</span> {</span><br><span class=\"line\"><span class=\"keyword\">public</span>:</span><br><span class=\"line\"><span class=\"built_in\">C</span>(C& a) = <span class=\"keyword\">delete</span>;</span><br><span class=\"line\">};</span><br><span class=\"line\">但是以下尝试声明删除函数的方法会产生错误:</span><br><span class=\"line\"><span class=\"comment\">// incorrect syntax of declaring a member function as deleted</span></span><br><span class=\"line\"><span class=\"keyword\">class</span> <span class=\"title class_\">C</span> {</span><br><span class=\"line\"><span class=\"keyword\">public</span>:</span><br><span class=\"line\"><span class=\"built_in\">C</span>();</span><br><span class=\"line\">};</span><br><span class=\"line\"><span class=\"comment\">// Error, the deleted definition of function C must be the first declaration of the function.</span></span><br><span class=\"line\">C::<span class=\"built_in\">C</span>() = <span class=\"keyword\">delete</span>;</span><br></pre></td></tr></table></figure>\n\n<h2 id=\"对象成员初始化\"><a href=\"#对象成员初始化\" class=\"headerlink\" title=\"对象成员初始化\"></a>对象成员初始化</h2><h4 id=\"默认成员初始化器\"><a href=\"#默认成员初始化器\" class=\"headerlink\" title=\"默认成员初始化器\"></a>默认成员初始化器</h4><p>它是成员声明中包含的花括号或等号初始化器</p>\n<h4 id=\"成员初始化器列表\"><a href=\"#成员初始化器列表\" class=\"headerlink\" title=\"成员初始化器列表\"></a>成员初始化器列表</h4><figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">struct</span> <span class=\"title class_\">Ray</span> {</span><br><span class=\"line\"><span class=\"built_in\">Ray</span> (Vector3 origin, Vector3</span><br><span class=\"line\">direction):<span class=\"built_in\">origin</span>(origin),<span class=\"built_in\">direction</span>(direction) {};</span><br><span class=\"line\">Vector3 origin; <span class=\"comment\">//射线的原点。</span></span><br><span class=\"line\">Vector3 direction; <span class=\"comment\">//射线的方向。</span></span><br><span class=\"line\">};</span><br></pre></td></tr></table></figure>\n\n<p><strong>必须使用初始化器列表的时候:</strong></p>\n<p>1.常量成员,因为常量只能初始化不能赋值,所以必须放在初始化器列表里面</p>\n<p>2.引用类型,引用必须在定义的时候初始化,并且不能重新赋值,所以也要使用初始化器</p>\n<p>3.没有无参构造函数的类成员,使用初始化器列表可以使用有参构造函数初始化</p>\n<p>成员是按照他们在类中声明的顺序进行初始化的,而不是按照他们在初始化器<br>列表出现的顺序初始化的:</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">class</span> <span class=\"title class_\">foo</span> {</span><br><span class=\"line\"><span class=\"keyword\">public</span>:</span><br><span class=\"line\"><span class=\"type\">int</span> i ;<span class=\"type\">int</span> j ;</span><br><span class=\"line\"><span class=\"built_in\">foo</span>(<span class=\"type\">int</span> x):<span class=\"built_in\">i</span>(x), <span class=\"built_in\">j</span>(i){}; <span class=\"comment\">// ok, 先初始化i,后初始化j</span></span><br><span class=\"line\">};</span><br></pre></td></tr></table></figure>\n","excerpt":"","more":"<h1 id=\"数据抽象和类-II\"><a href=\"#数据抽象和类-II\" class=\"headerlink\" title=\"数据抽象和类 II\"></a>数据抽象和类 II</h1><h2 id=\"C-与-C-动态对象(变量)管理\"><a href=\"#C-与-C-动态对象(变量)管理\" class=\"headerlink\" title=\"C 与 C++动态对象(变量)管理\"></a>C 与 C++动态对象(变量)管理</h2><p>堆(Heap)<br>• 共享的对象(变量)空间<br>• 由 stdlib 库管理</p>\n<h3 id=\"C\"><a href=\"#C\" class=\"headerlink\" title=\"C\"></a>C</h3><p>必须 #include <stdlib.h><br>• 申请空间,<code>void * malloc(size_t)</code><br>• 释放空间,<code>void free(void *)</code></p>\n<figure class=\"highlight c\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span><span class=\"string\"><stdio.h></span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span><span class=\"string\"><stdlib.h></span></span></span><br><span class=\"line\"><span class=\"keyword\">typedef</span> <span class=\"class\"><span class=\"keyword\">struct</span> {</span> <span class=\"type\">int</span> x; <span class=\"type\">int</span> y; } Point;</span><br><span class=\"line\"><span class=\"type\">int</span> <span class=\"title function_\">main</span><span class=\"params\">()</span> {</span><br><span class=\"line\"><span class=\"comment\">// 分配变量或一维可变数组</span></span><br><span class=\"line\">Point *p1 = <span class=\"built_in\">malloc</span>(<span class=\"keyword\">sizeof</span>(Point) * <span class=\"number\">10</span>);</span><br><span class=\"line\"><span class=\"comment\">// 分配二维数组(n,m是常数)</span></span><br><span class=\"line\">Point (*p2)[<span class=\"number\">2</span>][<span class=\"number\">3</span>] = <span class=\"built_in\">malloc</span>(<span class=\"keyword\">sizeof</span>(Point) * <span class=\"number\">6</span>);</span><br><span class=\"line\"><span class=\"comment\">// 分配数组的数组</span></span><br><span class=\"line\"><span class=\"type\">int</span> n = <span class=\"number\">2</span>, m = <span class=\"number\">3</span>;</span><br><span class=\"line\">Point **p3 = <span class=\"built_in\">malloc</span>(<span class=\"keyword\">sizeof</span>(Point *) * n);</span><br><span class=\"line\"><span class=\"keyword\">for</span> (<span class=\"type\">size_t</span> i = <span class=\"number\">0</span>; i < n; i++){</span><br><span class=\"line\">p3[i] = <span class=\"built_in\">malloc</span>(<span class=\"keyword\">sizeof</span>(Point) * m);</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"comment\">// do somesthing</span></span><br><span class=\"line\"><span class=\"built_in\">free</span>(p1);</span><br><span class=\"line\"><span class=\"built_in\">free</span>(p2);</span><br><span class=\"line\"><span class=\"comment\">// 必须先释放行数组</span></span><br><span class=\"line\"><span class=\"keyword\">for</span> (<span class=\"type\">size_t</span> i = <span class=\"number\">0</span>; i < n; i++){</span><br><span class=\"line\"><span class=\"built_in\">free</span>(p3[i]);</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"built_in\">free</span>(p3);</span><br><span class=\"line\"><span class=\"keyword\">return</span> <span class=\"number\">0</span>;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<h3 id=\"C-动态对象(变量)与对象指针\"><a href=\"#C-动态对象(变量)与对象指针\" class=\"headerlink\" title=\"C++ 动态对象(变量)与对象指针\"></a>C++ 动态对象(变量)与对象指针</h3><p><font color=red><strong>new 和 delete 运算符</strong></font><br><strong>new</strong><br>• 分配空间<br>• 每个对象调用构造器<br>• 若内存分配失败,<strong>抛出异常,不是 NULL</strong></p>\n<figure class=\"highlight actionscript\"><table><tr><td class=\"code\"><pre><span class=\"line\">指针=<span class=\"keyword\">new</span> 类型名;<span class=\"comment\">//动态创建一个对象</span></span><br><span class=\"line\">指针=<span class=\"keyword\">new</span> 类型名(初始化参数);<span class=\"comment\">//动态创建一个对象并指定初始化参数</span></span><br><span class=\"line\">指针=<span class=\"keyword\">new</span> 类型名[数组长度];<span class=\"comment\">//用于动态分配数组</span></span><br></pre></td></tr></table></figure>\n\n<p><strong>返回该类型的指针</strong><br>注:不是万能指针 <code>void *</code></p>\n<p><strong>delete []p</strong><br>• 为数组每个对象析构<br>• 释放空间</p>\n<figure class=\"highlight actionscript\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">delete</span> 变量名;<span class=\"comment\">//基本用法</span></span><br><span class=\"line\"><span class=\"keyword\">delete</span> []变量名;<span class=\"comment\">//用于释放数组</span></span><br></pre></td></tr></table></figure>\n\n<p>如果动态分配了一个数组,但是却用 delete p 的方式释放,没有用[],则编译时<br>没有问题,运行时可能不会发生错误,但实际上会导致动态分配的数组没有被完<br>全释放。</p>\n<p>用 delete 释放空间后,指针的值仍是原来指向的地址,但指针已无效(重复释放<br>将出错)</p>\n<p>例:</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span><span class=\"string\"><iostream></span></span></span><br><span class=\"line\"><span class=\"keyword\">using</span> <span class=\"keyword\">namespace</span> std;</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">void</span> <span class=\"title\">inc</span><span class=\"params\">(<span class=\"type\">int</span> *p, <span class=\"type\">int</span> Length)</span> </span>{</span><br><span class=\"line\"><span class=\"keyword\">for</span> (<span class=\"type\">int</span> i = <span class=\"number\">0</span>; i < Length; i++)</span><br><span class=\"line\">p[i]++;</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span><span class=\"params\">()</span> </span>{</span><br><span class=\"line\"><span class=\"type\">int</span> *p;</span><br><span class=\"line\"><span class=\"type\">int</span> Length, i;</span><br><span class=\"line\">cout << <span class=\"string\">"Enter the lenght you want: "</span>;</span><br><span class=\"line\">cin >> Length;</span><br><span class=\"line\">p = <span class=\"keyword\">new</span> <span class=\"type\">int</span>[Length]{<span class=\"number\">1</span>,<span class=\"number\">3</span>,<span class=\"number\">5</span>};</span><br><span class=\"line\"><span class=\"built_in\">inc</span>(p, Length);</span><br><span class=\"line\"><span class=\"keyword\">for</span> (i = <span class=\"number\">0</span> ; i < Length; i++)</span><br><span class=\"line\">cout << *(p+i) << <span class=\"string\">" "</span>;</span><br><span class=\"line\"><span class=\"keyword\">delete</span> []p;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<h4 id=\"对象指针访问成员\"><a href=\"#对象指针访问成员\" class=\"headerlink\" title=\"对象指针访问成员\"></a>对象指针访问成员</h4><figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span><span class=\"params\">()</span> </span>{</span><br><span class=\"line\">Text* str_ptr;</span><br><span class=\"line\"><span class=\"function\">Text <span class=\"title\">str</span><span class=\"params\">(<span class=\"string\">"on stack 1"</span>)</span></span>;</span><br><span class=\"line\">str_ptr = &str;<span class=\"comment\">//取对象地址</span></span><br><span class=\"line\">str.<span class=\"built_in\">Print</span>(); <span class=\"comment\">//对象取成员</span></span><br><span class=\"line\">str_ptr-><span class=\"built_in\">Print</span>();<span class=\"comment\">//指针取成员</span></span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<h2 id=\"delete-和-default\"><a href=\"#delete-和-default\" class=\"headerlink\" title=\"=delete 和 =default\"></a>=delete 和 =default</h2><h3 id=\"显式定义默认函数:-default\"><a href=\"#显式定义默认函数:-default\" class=\"headerlink\" title=\"显式定义默认函数:=default\"></a>显式定义默认函数:=default</h3><p>当我们声明有参构造函数时,编译器不会创建默认构造函数。</p>\n<p>• =default 必须在函数申明后,让编译创建该构造函数</p>\n<p><strong>• 特殊成员函数包括:</strong><br>➢ 默认构造函数:T()<br>➢ 析构函数:~T()<br>➢ 复制构造函数:T(const T&)<br>➢ 赋值运算:operator=(const T&)<br>➢ …</p>\n<p>• 函数不能再自定义实现<br>例:</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span> <span class=\"string\"><iostream></span></span></span><br><span class=\"line\"><span class=\"keyword\">using</span> <span class=\"keyword\">namespace</span> std;</span><br><span class=\"line\"><span class=\"keyword\">class</span> <span class=\"title class_\">A</span></span><br><span class=\"line\">{</span><br><span class=\"line\"><span class=\"keyword\">public</span>:</span><br><span class=\"line\"><span class=\"built_in\">A</span>(<span class=\"type\">int</span> x) {</span><br><span class=\"line\">cout << <span class=\"string\">"This is a parameterized constructor"</span>;</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"built_in\">A</span>() = <span class=\"keyword\">default</span>;</span><br><span class=\"line\">};</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span><span class=\"params\">()</span></span>{</span><br><span class=\"line\">A a; <span class=\"comment\">//call A()</span></span><br><span class=\"line\"><span class=\"function\">A <span class=\"title\">x</span><span class=\"params\">(<span class=\"number\">1</span>)</span></span>; <span class=\"comment\">//call A(int x)</span></span><br><span class=\"line\">cout<<endl;</span><br><span class=\"line\"><span class=\"keyword\">return</span> <span class=\"number\">0</span>;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<h3 id=\"弃置函数:-delete\"><a href=\"#弃置函数:-delete\" class=\"headerlink\" title=\"弃置函数:=delete\"></a>弃置函数:=delete</h3><p>任何弃置函数的使用都是非良构的(程序无法编译)</p>\n<p>删除的函数是隐式内联的,这一点非常重要,删除的函数定义必须是函数的<strong>首次声明</strong></p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\">例:</span><br><span class=\"line\"><span class=\"keyword\">class</span> <span class=\"title class_\">A</span> {</span><br><span class=\"line\"><span class=\"keyword\">public</span>:</span><br><span class=\"line\"><span class=\"built_in\">A</span>(<span class=\"type\">int</span> x): <span class=\"built_in\">m</span>(x) { }</span><br><span class=\"line\"><span class=\"comment\">// Delete the copy constructor</span></span><br><span class=\"line\"><span class=\"built_in\">A</span>(<span class=\"type\">const</span> A&) = <span class=\"keyword\">delete</span>;</span><br><span class=\"line\"><span class=\"comment\">// Delete the copy assignment operator</span></span><br><span class=\"line\">A& <span class=\"keyword\">operator</span>=(<span class=\"type\">const</span> A&) = <span class=\"keyword\">delete</span>;</span><br><span class=\"line\"><span class=\"type\">int</span> m;</span><br><span class=\"line\">};</span><br><span class=\"line\"></span><br><span class=\"line\">以下方法是将函数声明为已删除的正确方法:</span><br><span class=\"line\"><span class=\"keyword\">class</span> <span class=\"title class_\">C</span> {</span><br><span class=\"line\"><span class=\"keyword\">public</span>:</span><br><span class=\"line\"><span class=\"built_in\">C</span>(C& a) = <span class=\"keyword\">delete</span>;</span><br><span class=\"line\">};</span><br><span class=\"line\">但是以下尝试声明删除函数的方法会产生错误:</span><br><span class=\"line\"><span class=\"comment\">// incorrect syntax of declaring a member function as deleted</span></span><br><span class=\"line\"><span class=\"keyword\">class</span> <span class=\"title class_\">C</span> {</span><br><span class=\"line\"><span class=\"keyword\">public</span>:</span><br><span class=\"line\"><span class=\"built_in\">C</span>();</span><br><span class=\"line\">};</span><br><span class=\"line\"><span class=\"comment\">// Error, the deleted definition of function C must be the first declaration of the function.</span></span><br><span class=\"line\">C::<span class=\"built_in\">C</span>() = <span class=\"keyword\">delete</span>;</span><br></pre></td></tr></table></figure>\n\n<h2 id=\"对象成员初始化\"><a href=\"#对象成员初始化\" class=\"headerlink\" title=\"对象成员初始化\"></a>对象成员初始化</h2><h4 id=\"默认成员初始化器\"><a href=\"#默认成员初始化器\" class=\"headerlink\" title=\"默认成员初始化器\"></a>默认成员初始化器</h4><p>它是成员声明中包含的花括号或等号初始化器</p>\n<h4 id=\"成员初始化器列表\"><a href=\"#成员初始化器列表\" class=\"headerlink\" title=\"成员初始化器列表\"></a>成员初始化器列表</h4><figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">struct</span> <span class=\"title class_\">Ray</span> {</span><br><span class=\"line\"><span class=\"built_in\">Ray</span> (Vector3 origin, Vector3</span><br><span class=\"line\">direction):<span class=\"built_in\">origin</span>(origin),<span class=\"built_in\">direction</span>(direction) {};</span><br><span class=\"line\">Vector3 origin; <span class=\"comment\">//射线的原点。</span></span><br><span class=\"line\">Vector3 direction; <span class=\"comment\">//射线的方向。</span></span><br><span class=\"line\">};</span><br></pre></td></tr></table></figure>\n\n<p><strong>必须使用初始化器列表的时候:</strong></p>\n<p>1.常量成员,因为常量只能初始化不能赋值,所以必须放在初始化器列表里面</p>\n<p>2.引用类型,引用必须在定义的时候初始化,并且不能重新赋值,所以也要使用初始化器</p>\n<p>3.没有无参构造函数的类成员,使用初始化器列表可以使用有参构造函数初始化</p>\n<p>成员是按照他们在类中声明的顺序进行初始化的,而不是按照他们在初始化器<br>列表出现的顺序初始化的:</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">class</span> <span class=\"title class_\">foo</span> {</span><br><span class=\"line\"><span class=\"keyword\">public</span>:</span><br><span class=\"line\"><span class=\"type\">int</span> i ;<span class=\"type\">int</span> j ;</span><br><span class=\"line\"><span class=\"built_in\">foo</span>(<span class=\"type\">int</span> x):<span class=\"built_in\">i</span>(x), <span class=\"built_in\">j</span>(i){}; <span class=\"comment\">// ok, 先初始化i,后初始化j</span></span><br><span class=\"line\">};</span><br></pre></td></tr></table></figure>\n"},{"title":"排序","top_img":"transparent","comments":0,"_content":"\n# 排序\n\n## sort 函数\n\nort 是 C++ <algorithm> 库中的一个高效排序函数,基于 快速排序 或 内省排序 实现,平均时间复杂度 O(n log n)\n\n**默认升序排序(从小到大)**\n\n而实现其他排序方式可以自己编写一个函数 cmp 作为 sort 的第三个参数\n例:\n\n```cpp\n#include<bits/stdc++.h>\nusing namespace std;\nstruct di{\n int x;\n int y;\n int z;\n};\nbool cmp(di a,di b){\n if(a.z>b.z){\n return 1;\n }\n else{\n return 0;\n }\n}\ndouble jl(di a,di b){\n return sqrt(pow(a.x-b.x,2)+pow(a.y-b.y,2)+pow(a.z-b.z,2));\n}\nint n;\nint main(){\n cin>>n;\n struct di din[n+2];\n for (int i = 0; i < n; i++){\n cin>>din[i].x>>din[i].y>>din[i].z;\n }\n sort(din,din+n,cmp);\n double sum=0.0;\n for (int i = 0; i < n-1; i++){\n sum+=jl(din[i+1],din[i]);\n }\n cout<<fixed<<setprecision(3)<<sum<<endl;\n return 0;\n}\n```\n\n## 桶排序\n\n```cpp\n#include<bits/stdc++.h>\nusing namespace std;\nint g;\nint main(){\n int n;\n int N[105];\n bool a[1001]={0};\n cin>>n;\n //去重,排序\n //桶排序\n for (int i = 0; i < n; i++){\n cin>>N[i];\n if(a[N[i]]==0){\n g++;\n }\n a[N[i]]=1;\n }\n cout<<g<<endl;\n for (int i = 0; i < 1000; i++){\n if(a[i]){\n cout<<i<<' ';\n }\n }\n return 0;\n}\n```\n\n比较大小时可考虑利用字典序,有奇效\n","source":"_posts/eigth-blog.md","raw":"---\ntitle: 排序\ntags: 算法\ntop_img: transparent\ncomments: false\n---\n\n# 排序\n\n## sort 函数\n\nort 是 C++ <algorithm> 库中的一个高效排序函数,基于 快速排序 或 内省排序 实现,平均时间复杂度 O(n log n)\n\n**默认升序排序(从小到大)**\n\n而实现其他排序方式可以自己编写一个函数 cmp 作为 sort 的第三个参数\n例:\n\n```cpp\n#include<bits/stdc++.h>\nusing namespace std;\nstruct di{\n int x;\n int y;\n int z;\n};\nbool cmp(di a,di b){\n if(a.z>b.z){\n return 1;\n }\n else{\n return 0;\n }\n}\ndouble jl(di a,di b){\n return sqrt(pow(a.x-b.x,2)+pow(a.y-b.y,2)+pow(a.z-b.z,2));\n}\nint n;\nint main(){\n cin>>n;\n struct di din[n+2];\n for (int i = 0; i < n; i++){\n cin>>din[i].x>>din[i].y>>din[i].z;\n }\n sort(din,din+n,cmp);\n double sum=0.0;\n for (int i = 0; i < n-1; i++){\n sum+=jl(din[i+1],din[i]);\n }\n cout<<fixed<<setprecision(3)<<sum<<endl;\n return 0;\n}\n```\n\n## 桶排序\n\n```cpp\n#include<bits/stdc++.h>\nusing namespace std;\nint g;\nint main(){\n int n;\n int N[105];\n bool a[1001]={0};\n cin>>n;\n //去重,排序\n //桶排序\n for (int i = 0; i < n; i++){\n cin>>N[i];\n if(a[N[i]]==0){\n g++;\n }\n a[N[i]]=1;\n }\n cout<<g<<endl;\n for (int i = 0; i < 1000; i++){\n if(a[i]){\n cout<<i<<' ';\n }\n }\n return 0;\n}\n```\n\n比较大小时可考虑利用字典序,有奇效\n","slug":"eigth-blog","published":1,"date":"2025-04-10T07:12:34.589Z","updated":"2025-04-10T07:13:12.830Z","layout":"post","photos":[],"_id":"cmkmd8tyt0006cw64fnqq58r3","content":"<link rel=\"stylesheet\" class=\"aplayer-secondary-style-marker\" href=\"\\assets\\css\\APlayer.min.css\"><script src=\"\\assets\\js\\APlayer.min.js\" class=\"aplayer-secondary-script-marker\"></script><h1 id=\"排序\"><a href=\"#排序\" class=\"headerlink\" title=\"排序\"></a>排序</h1><h2 id=\"sort-函数\"><a href=\"#sort-函数\" class=\"headerlink\" title=\"sort 函数\"></a>sort 函数</h2><p>ort 是 C++ <algorithm> 库中的一个高效排序函数,基于 快速排序 或 内省排序 实现,平均时间复杂度 O(n log n)</p>\n<p><strong>默认升序排序(从小到大)</strong></p>\n<p>而实现其他排序方式可以自己编写一个函数 cmp 作为 sort 的第三个参数<br>例:</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span><span class=\"string\"><bits/stdc++.h></span></span></span><br><span class=\"line\"><span class=\"keyword\">using</span> <span class=\"keyword\">namespace</span> std;</span><br><span class=\"line\"><span class=\"keyword\">struct</span> <span class=\"title class_\">di</span>{</span><br><span class=\"line\"> <span class=\"type\">int</span> x;</span><br><span class=\"line\"> <span class=\"type\">int</span> y;</span><br><span class=\"line\"> <span class=\"type\">int</span> z;</span><br><span class=\"line\">};</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">bool</span> <span class=\"title\">cmp</span><span class=\"params\">(di a,di b)</span></span>{</span><br><span class=\"line\"> <span class=\"keyword\">if</span>(a.z>b.z){</span><br><span class=\"line\"> <span class=\"keyword\">return</span> <span class=\"number\">1</span>;</span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"keyword\">else</span>{</span><br><span class=\"line\"> <span class=\"keyword\">return</span> <span class=\"number\">0</span>;</span><br><span class=\"line\"> }</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">double</span> <span class=\"title\">jl</span><span class=\"params\">(di a,di b)</span></span>{</span><br><span class=\"line\"> <span class=\"keyword\">return</span> <span class=\"built_in\">sqrt</span>(<span class=\"built_in\">pow</span>(a.x-b.x,<span class=\"number\">2</span>)+<span class=\"built_in\">pow</span>(a.y-b.y,<span class=\"number\">2</span>)+<span class=\"built_in\">pow</span>(a.z-b.z,<span class=\"number\">2</span>));</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"type\">int</span> n;</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span><span class=\"params\">()</span></span>{</span><br><span class=\"line\"> cin>>n;</span><br><span class=\"line\"> <span class=\"keyword\">struct</span> <span class=\"title class_\">di</span> din[n<span class=\"number\">+2</span>];</span><br><span class=\"line\"> <span class=\"keyword\">for</span> (<span class=\"type\">int</span> i = <span class=\"number\">0</span>; i < n; i++){</span><br><span class=\"line\"> cin>>din[i].x>>din[i].y>>din[i].z;</span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"built_in\">sort</span>(din,din+n,cmp);</span><br><span class=\"line\"> <span class=\"type\">double</span> sum=<span class=\"number\">0.0</span>;</span><br><span class=\"line\"> <span class=\"keyword\">for</span> (<span class=\"type\">int</span> i = <span class=\"number\">0</span>; i < n<span class=\"number\">-1</span>; i++){</span><br><span class=\"line\"> sum+=<span class=\"built_in\">jl</span>(din[i<span class=\"number\">+1</span>],din[i]);</span><br><span class=\"line\"> }</span><br><span class=\"line\"> cout<<fixed<<<span class=\"built_in\">setprecision</span>(<span class=\"number\">3</span>)<<sum<<endl;</span><br><span class=\"line\"> <span class=\"keyword\">return</span> <span class=\"number\">0</span>;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<h2 id=\"桶排序\"><a href=\"#桶排序\" class=\"headerlink\" title=\"桶排序\"></a>桶排序</h2><figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span><span class=\"string\"><bits/stdc++.h></span></span></span><br><span class=\"line\"><span class=\"keyword\">using</span> <span class=\"keyword\">namespace</span> std;</span><br><span class=\"line\"><span class=\"type\">int</span> g;</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span><span class=\"params\">()</span></span>{</span><br><span class=\"line\"> <span class=\"type\">int</span> n;</span><br><span class=\"line\"> <span class=\"type\">int</span> N[<span class=\"number\">105</span>];</span><br><span class=\"line\"> <span class=\"type\">bool</span> a[<span class=\"number\">1001</span>]={<span class=\"number\">0</span>};</span><br><span class=\"line\"> cin>>n;</span><br><span class=\"line\"> <span class=\"comment\">//去重,排序</span></span><br><span class=\"line\"> <span class=\"comment\">//桶排序</span></span><br><span class=\"line\"> <span class=\"keyword\">for</span> (<span class=\"type\">int</span> i = <span class=\"number\">0</span>; i < n; i++){</span><br><span class=\"line\"> cin>>N[i];</span><br><span class=\"line\"> <span class=\"keyword\">if</span>(a[N[i]]==<span class=\"number\">0</span>){</span><br><span class=\"line\"> g++;</span><br><span class=\"line\"> }</span><br><span class=\"line\"> a[N[i]]=<span class=\"number\">1</span>;</span><br><span class=\"line\"> }</span><br><span class=\"line\"> cout<<g<<endl;</span><br><span class=\"line\"> <span class=\"keyword\">for</span> (<span class=\"type\">int</span> i = <span class=\"number\">0</span>; i < <span class=\"number\">1000</span>; i++){</span><br><span class=\"line\"> <span class=\"keyword\">if</span>(a[i]){</span><br><span class=\"line\"> cout<<i<<<span class=\"string\">' '</span>;</span><br><span class=\"line\"> }</span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"keyword\">return</span> <span class=\"number\">0</span>;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<p>比较大小时可考虑利用字典序,有奇效</p>\n","excerpt":"","more":"<h1 id=\"排序\"><a href=\"#排序\" class=\"headerlink\" title=\"排序\"></a>排序</h1><h2 id=\"sort-函数\"><a href=\"#sort-函数\" class=\"headerlink\" title=\"sort 函数\"></a>sort 函数</h2><p>ort 是 C++ <algorithm> 库中的一个高效排序函数,基于 快速排序 或 内省排序 实现,平均时间复杂度 O(n log n)</p>\n<p><strong>默认升序排序(从小到大)</strong></p>\n<p>而实现其他排序方式可以自己编写一个函数 cmp 作为 sort 的第三个参数<br>例:</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span><span class=\"string\"><bits/stdc++.h></span></span></span><br><span class=\"line\"><span class=\"keyword\">using</span> <span class=\"keyword\">namespace</span> std;</span><br><span class=\"line\"><span class=\"keyword\">struct</span> <span class=\"title class_\">di</span>{</span><br><span class=\"line\"> <span class=\"type\">int</span> x;</span><br><span class=\"line\"> <span class=\"type\">int</span> y;</span><br><span class=\"line\"> <span class=\"type\">int</span> z;</span><br><span class=\"line\">};</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">bool</span> <span class=\"title\">cmp</span><span class=\"params\">(di a,di b)</span></span>{</span><br><span class=\"line\"> <span class=\"keyword\">if</span>(a.z>b.z){</span><br><span class=\"line\"> <span class=\"keyword\">return</span> <span class=\"number\">1</span>;</span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"keyword\">else</span>{</span><br><span class=\"line\"> <span class=\"keyword\">return</span> <span class=\"number\">0</span>;</span><br><span class=\"line\"> }</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">double</span> <span class=\"title\">jl</span><span class=\"params\">(di a,di b)</span></span>{</span><br><span class=\"line\"> <span class=\"keyword\">return</span> <span class=\"built_in\">sqrt</span>(<span class=\"built_in\">pow</span>(a.x-b.x,<span class=\"number\">2</span>)+<span class=\"built_in\">pow</span>(a.y-b.y,<span class=\"number\">2</span>)+<span class=\"built_in\">pow</span>(a.z-b.z,<span class=\"number\">2</span>));</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"type\">int</span> n;</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span><span class=\"params\">()</span></span>{</span><br><span class=\"line\"> cin>>n;</span><br><span class=\"line\"> <span class=\"keyword\">struct</span> <span class=\"title class_\">di</span> din[n<span class=\"number\">+2</span>];</span><br><span class=\"line\"> <span class=\"keyword\">for</span> (<span class=\"type\">int</span> i = <span class=\"number\">0</span>; i < n; i++){</span><br><span class=\"line\"> cin>>din[i].x>>din[i].y>>din[i].z;</span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"built_in\">sort</span>(din,din+n,cmp);</span><br><span class=\"line\"> <span class=\"type\">double</span> sum=<span class=\"number\">0.0</span>;</span><br><span class=\"line\"> <span class=\"keyword\">for</span> (<span class=\"type\">int</span> i = <span class=\"number\">0</span>; i < n<span class=\"number\">-1</span>; i++){</span><br><span class=\"line\"> sum+=<span class=\"built_in\">jl</span>(din[i<span class=\"number\">+1</span>],din[i]);</span><br><span class=\"line\"> }</span><br><span class=\"line\"> cout<<fixed<<<span class=\"built_in\">setprecision</span>(<span class=\"number\">3</span>)<<sum<<endl;</span><br><span class=\"line\"> <span class=\"keyword\">return</span> <span class=\"number\">0</span>;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<h2 id=\"桶排序\"><a href=\"#桶排序\" class=\"headerlink\" title=\"桶排序\"></a>桶排序</h2><figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span><span class=\"string\"><bits/stdc++.h></span></span></span><br><span class=\"line\"><span class=\"keyword\">using</span> <span class=\"keyword\">namespace</span> std;</span><br><span class=\"line\"><span class=\"type\">int</span> g;</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span><span class=\"params\">()</span></span>{</span><br><span class=\"line\"> <span class=\"type\">int</span> n;</span><br><span class=\"line\"> <span class=\"type\">int</span> N[<span class=\"number\">105</span>];</span><br><span class=\"line\"> <span class=\"type\">bool</span> a[<span class=\"number\">1001</span>]={<span class=\"number\">0</span>};</span><br><span class=\"line\"> cin>>n;</span><br><span class=\"line\"> <span class=\"comment\">//去重,排序</span></span><br><span class=\"line\"> <span class=\"comment\">//桶排序</span></span><br><span class=\"line\"> <span class=\"keyword\">for</span> (<span class=\"type\">int</span> i = <span class=\"number\">0</span>; i < n; i++){</span><br><span class=\"line\"> cin>>N[i];</span><br><span class=\"line\"> <span class=\"keyword\">if</span>(a[N[i]]==<span class=\"number\">0</span>){</span><br><span class=\"line\"> g++;</span><br><span class=\"line\"> }</span><br><span class=\"line\"> a[N[i]]=<span class=\"number\">1</span>;</span><br><span class=\"line\"> }</span><br><span class=\"line\"> cout<<g<<endl;</span><br><span class=\"line\"> <span class=\"keyword\">for</span> (<span class=\"type\">int</span> i = <span class=\"number\">0</span>; i < <span class=\"number\">1000</span>; i++){</span><br><span class=\"line\"> <span class=\"keyword\">if</span>(a[i]){</span><br><span class=\"line\"> cout<<i<<<span class=\"string\">' '</span>;</span><br><span class=\"line\"> }</span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"keyword\">return</span> <span class=\"number\">0</span>;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<p>比较大小时可考虑利用字典序,有奇效</p>\n"},{"title":"博客更新日志","top_img":"transparent","comments":0,"_content":"\n# 2.24\n\n**博客部署**\n\n用[hexo](#)和[butterfly](https://butterfly.js.org/)搭建的个人博客,用于记录知识与学习经验,还在持续更新中\n\n# 2.26\n\n**鼓搞了音乐功能**\n\n# 3.3\n\n**鼓搞了代码块高亮功能**\n\n# 3.4\n\n**调整主题样式,添加友链**\n\n# 3.5\n\n**增添评论**\n\n---\n\n# 网站构建和部署\n\n这一项 CSDN 等各个平台上都有详细的教程,在此便不再讲述,因此在此写出应用 butterfly 主题后的美化和常见问题\n\n## 1.主题页面的美化\n\n在这里插入主题图片\n\n```yml\nbackgound:\n\n//如果为 backgound_img: 则直接将其改为 backgound:\n```\n\n将这些全部设为 transparent,意为透明\n\n```yml\nfooter_img: transparent\ndefault_top_img: transparent\nindex_img: transparent\n```\n\n这时会有黑色半透遮罩,在这里调整即可\n\n```yml\nmask:\n header: false\n footer: true\n```\n\n在文章的 md 文档里设置 front-matter 中的 top_img\n\n```\ntop_img: transparent\n```\n\n否则文章顶部会显示 cover 的图片\n","source":"_posts/hello-world.md","raw":"---\ntitle: 博客更新日志\ntags: 博客构建\ntop_img: transparent\ncomments: false\n---\n\n# 2.24\n\n**博客部署**\n\n用[hexo](#)和[butterfly](https://butterfly.js.org/)搭建的个人博客,用于记录知识与学习经验,还在持续更新中\n\n# 2.26\n\n**鼓搞了音乐功能**\n\n# 3.3\n\n**鼓搞了代码块高亮功能**\n\n# 3.4\n\n**调整主题样式,添加友链**\n\n# 3.5\n\n**增添评论**\n\n---\n\n# 网站构建和部署\n\n这一项 CSDN 等各个平台上都有详细的教程,在此便不再讲述,因此在此写出应用 butterfly 主题后的美化和常见问题\n\n## 1.主题页面的美化\n\n在这里插入主题图片\n\n```yml\nbackgound:\n\n//如果为 backgound_img: 则直接将其改为 backgound:\n```\n\n将这些全部设为 transparent,意为透明\n\n```yml\nfooter_img: transparent\ndefault_top_img: transparent\nindex_img: transparent\n```\n\n这时会有黑色半透遮罩,在这里调整即可\n\n```yml\nmask:\n header: false\n footer: true\n```\n\n在文章的 md 文档里设置 front-matter 中的 top_img\n\n```\ntop_img: transparent\n```\n\n否则文章顶部会显示 cover 的图片\n","slug":"hello-world","published":1,"date":"2025-02-24T11:29:04.259Z","updated":"2025-03-05T07:05:13.032Z","layout":"post","photos":[],"_id":"cmkmd8tyu0007cw64667s6ika","content":"<link rel=\"stylesheet\" class=\"aplayer-secondary-style-marker\" href=\"\\assets\\css\\APlayer.min.css\"><script src=\"\\assets\\js\\APlayer.min.js\" class=\"aplayer-secondary-script-marker\"></script><h1 id=\"2-24\"><a href=\"#2-24\" class=\"headerlink\" title=\"2.24\"></a>2.24</h1><p><strong>博客部署</strong></p>\n<p>用<a href=\"#\">hexo</a>和<a href=\"https://butterfly.js.org/\">butterfly</a>搭建的个人博客,用于记录知识与学习经验,还在持续更新中</p>\n<h1 id=\"2-26\"><a href=\"#2-26\" class=\"headerlink\" title=\"2.26\"></a>2.26</h1><p><strong>鼓搞了音乐功能</strong></p>\n<h1 id=\"3-3\"><a href=\"#3-3\" class=\"headerlink\" title=\"3.3\"></a>3.3</h1><p><strong>鼓搞了代码块高亮功能</strong></p>\n<h1 id=\"3-4\"><a href=\"#3-4\" class=\"headerlink\" title=\"3.4\"></a>3.4</h1><p><strong>调整主题样式,添加友链</strong></p>\n<h1 id=\"3-5\"><a href=\"#3-5\" class=\"headerlink\" title=\"3.5\"></a>3.5</h1><p><strong>增添评论</strong></p>\n<hr>\n<h1 id=\"网站构建和部署\"><a href=\"#网站构建和部署\" class=\"headerlink\" title=\"网站构建和部署\"></a>网站构建和部署</h1><p>这一项 CSDN 等各个平台上都有详细的教程,在此便不再讲述,因此在此写出应用 butterfly 主题后的美化和常见问题</p>\n<h2 id=\"1-主题页面的美化\"><a href=\"#1-主题页面的美化\" class=\"headerlink\" title=\"1.主题页面的美化\"></a>1.主题页面的美化</h2><p>在这里插入主题图片</p>\n<figure class=\"highlight yml\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"attr\">backgound:</span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"string\">//如果为</span> <span class=\"attr\">backgound_img:</span> <span class=\"string\">则直接将其改为</span> <span class=\"attr\">backgound:</span></span><br></pre></td></tr></table></figure>\n\n<p>将这些全部设为 transparent,意为透明</p>\n<figure class=\"highlight yml\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"attr\">footer_img:</span> <span class=\"string\">transparent</span></span><br><span class=\"line\"><span class=\"attr\">default_top_img:</span> <span class=\"string\">transparent</span></span><br><span class=\"line\"><span class=\"attr\">index_img:</span> <span class=\"string\">transparent</span></span><br></pre></td></tr></table></figure>\n\n<p>这时会有黑色半透遮罩,在这里调整即可</p>\n<figure class=\"highlight yml\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"attr\">mask:</span></span><br><span class=\"line\"> <span class=\"attr\">header:</span> <span class=\"literal\">false</span></span><br><span class=\"line\"> <span class=\"attr\">footer:</span> <span class=\"literal\">true</span></span><br></pre></td></tr></table></figure>\n\n<p>在文章的 md 文档里设置 front-matter 中的 top_img</p>\n<figure class=\"highlight avrasm\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"symbol\">top_img:</span> transparent</span><br></pre></td></tr></table></figure>\n\n<p>否则文章顶部会显示 cover 的图片</p>\n","excerpt":"","more":"<h1 id=\"2-24\"><a href=\"#2-24\" class=\"headerlink\" title=\"2.24\"></a>2.24</h1><p><strong>博客部署</strong></p>\n<p>用<a href=\"#\">hexo</a>和<a href=\"https://butterfly.js.org/\">butterfly</a>搭建的个人博客,用于记录知识与学习经验,还在持续更新中</p>\n<h1 id=\"2-26\"><a href=\"#2-26\" class=\"headerlink\" title=\"2.26\"></a>2.26</h1><p><strong>鼓搞了音乐功能</strong></p>\n<h1 id=\"3-3\"><a href=\"#3-3\" class=\"headerlink\" title=\"3.3\"></a>3.3</h1><p><strong>鼓搞了代码块高亮功能</strong></p>\n<h1 id=\"3-4\"><a href=\"#3-4\" class=\"headerlink\" title=\"3.4\"></a>3.4</h1><p><strong>调整主题样式,添加友链</strong></p>\n<h1 id=\"3-5\"><a href=\"#3-5\" class=\"headerlink\" title=\"3.5\"></a>3.5</h1><p><strong>增添评论</strong></p>\n<hr>\n<h1 id=\"网站构建和部署\"><a href=\"#网站构建和部署\" class=\"headerlink\" title=\"网站构建和部署\"></a>网站构建和部署</h1><p>这一项 CSDN 等各个平台上都有详细的教程,在此便不再讲述,因此在此写出应用 butterfly 主题后的美化和常见问题</p>\n<h2 id=\"1-主题页面的美化\"><a href=\"#1-主题页面的美化\" class=\"headerlink\" title=\"1.主题页面的美化\"></a>1.主题页面的美化</h2><p>在这里插入主题图片</p>\n<figure class=\"highlight yml\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"attr\">backgound:</span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"string\">//如果为</span> <span class=\"attr\">backgound_img:</span> <span class=\"string\">则直接将其改为</span> <span class=\"attr\">backgound:</span></span><br></pre></td></tr></table></figure>\n\n<p>将这些全部设为 transparent,意为透明</p>\n<figure class=\"highlight yml\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"attr\">footer_img:</span> <span class=\"string\">transparent</span></span><br><span class=\"line\"><span class=\"attr\">default_top_img:</span> <span class=\"string\">transparent</span></span><br><span class=\"line\"><span class=\"attr\">index_img:</span> <span class=\"string\">transparent</span></span><br></pre></td></tr></table></figure>\n\n<p>这时会有黑色半透遮罩,在这里调整即可</p>\n<figure class=\"highlight yml\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"attr\">mask:</span></span><br><span class=\"line\"> <span class=\"attr\">header:</span> <span class=\"literal\">false</span></span><br><span class=\"line\"> <span class=\"attr\">footer:</span> <span class=\"literal\">true</span></span><br></pre></td></tr></table></figure>\n\n<p>在文章的 md 文档里设置 front-matter 中的 top_img</p>\n<figure class=\"highlight avrasm\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"symbol\">top_img:</span> transparent</span><br></pre></td></tr></table></figure>\n\n<p>否则文章顶部会显示 cover 的图片</p>\n"},{"title":"异常处理","top_img":"transparent","comments":0,"_content":"\n# 异常处理概述\n\n## 程序终止\n\n1.执行正常结束而终止\n\n2.程序执行中发生错误或特殊事件而终止(异常终止)\n• 可预测的错误\n• 用户自己定义的错误\n• 难以预测的错误\n\n## 异常处理(exception handling)机制的基本思想\n\n• 采用结构化方法对程序的运行时错误进行**显式管理**:\n\n1.处理的是可预料的错误或特殊事件 2.将程序中的正常处理代码与异常处理代码显式区别开来,提高程序的可\n读性\n\n## C++语言中的异常处理\n\n抛出**异常与异常处理**分离的实现\n\n<font color=red>**Try-Catch 执行机制**</font>\n\n• 若程序有异常,则通过 throw 关键字创建一个异常对象,并抛出\n\n• 将可能抛出异常的程序段嵌在 try 块保护段之中,控制通过正常的顺序执行到达 try 块,然后执行 try 子块内的保护段\n\n• 如果在保护段执行期间没有引发异常,那么跟在 try 子块后的 catch 子句就不执行。\n程序继续执行紧跟在 try 块中最后一个 catch 子句后面的语句\n\n• 如果有异常,catch 子句按其在 try 块后出现的顺序被检查。类型匹配的 catch 子句将捕获并处理异常(或继续抛出异常)\n\n• 如果找不到匹配的处理代码,则自动调用标准库函数 terminate,其默认功能是调用 abort( )终止程序\n\n# 异常定义与抛出\n\n## throw 关键字\n\n```\nthrow 表达式; (1)\nthrow; (2)用于当前异常再抛出\n```\n\n• 表达式可以是任意类型的对象\n\n• throw 表达式; 操作的基本行为:\n\n1. 复制被抛出的对象为临时对象,作为异常对象\n2. 如果在当前函数 try 块中,则中止 try 执行,执行 catch 语句捕获\n3. 如有异常对象未在当前函数被捕获处理,则中止函数执行,异常传播给调用者处理\n\n例:\n\n```cpp\n#include <cstdio>\n#include <cerrno>\nint main () {\nFILE * pf;\ntry {\npf = fopen (\"unexist.txt\", \"rb\");\nif (pf == NULL) throw errno;\n// write something;\nfclose (pf);\n}\ncatch (int errnum) {\nif (errnum!=2) fclose (pf);\nelse perror(\"unexist.txt\");\n}\nreturn 0;\n}\n```\n\n## 异常基类 exception\n\n```cpp\nclass exception {\npublic:\nexception () noexcept;\nexception (const exception&) noexcept;\nexception& operator= (const exception&) noexcept;\nvirtual ~exception();\nvirtual const char* what() const noexcept;\n}\n```\n\n```cpp\n// bad_alloc example\n#include <iostream> // std::cout\n#include <new> // std::bad_alloc\nint main () {\ntry\n{\nint* myarray= new int[10000];\n}\ncatch (std::bad_alloc& ba)\n{\nstd::cerr << \"bad_alloc caught: \" << ba.what() << '\\n';\n}\nreturn 0;\n}\n```\n\n```cpp\n// out_of_range example\n#include <iostream> // std::cerr\n#include <stdexcept> // std::out_of_range\n#include <vector> // std::vector\nint main (void) {\nstd::vector<int> myvector(10);\ntry {\nmyvector.at(20)=100; // vector::at throws an out-of-range\n}\ncatch (const std::out_of_range& oor) {\nstd::cerr << \"Out of Range error: \" << oor.what() << '\\n';\n}\nreturn 0;\n}\n```\n\n# 异常的捕获及处理\n\n异常处理语法结构\n\n```cpp\ntry {\nprogram-statements //程序的正常处理逻辑\nthrow exception-object\nprogram-statements //程序的正常处理逻辑\n…\n}\ncatch (exception-declaration) {\nhandler-statements //异常处理代码\n}\ncatch (exception-declaration) {\nhandler-statements //异常处理代码\n}\n…\ncatch (…) {\nhandler-statements //异常处理代码\n}\n```\n\n## 异常捕获的匹配规则\n\n1.try 期间发生异常; 2.按 catch 顺序与异常定义匹配\n异常对象类型是定义类型或是定义类型的子类\n• 匹配成功\n• 异常接收变量是值,复制异常到接收变量\n• 异常接收变量是引用或指针,创建引用和指针\n• 清除当前异常,执行该异常处理块 3.直到匹配成功或结束\n**要点:**\n• <font color=red>**子类必须优先基类 catch,(…)必须是最后 catch**</font>\n• 用**基类引用类型捕捉异常,且虚函数才能产生多态**\n\n## 异常传播\n\n• 从异常抛出到控制转移给合适的异常处理语句的过程就叫做异常传播。\n\n• 异常传播过程(<font color=red>**一句话:当前函数未处理异常,则交给调用函数**</font>):\n\n1.由里层向外层的执行每一个包围抛出点(异常被抛出的最初位置)的 try 语句。 2.如果当前的成员函数调用中没能定位异常处理,则调用终止。并且在该成员函数调用点将该异常抛给调用者,重复执行上一步。 3.如果该异常终止了当前线程或进程的所有成员函数调用,则说明该线程或进程中不存在对异常的处理,它将自行终止。\n\n## 限定函数异常\n\n```cpp\nvoid f3(int x) throw(double,float) {\nswitch (x) {\ncase 1: throw 3.4; // 抛出double型异常\n case 2: throw 2.5f; // 抛出float型异常\n case 3: throw 1; // 抛出int型异常\n case 5: throw exception(); //抛出标准异常\n }\ncout << \"End of f3\" << endl;\n}\n```\n\n## noexcept 关键字\n\n```cpp\nvoid f2(int x) noexcept {\ntry {\nf3(x);\n}\ncatch (int) { //int型异常的处理代码\n cout << \"An int exception occurred!--from f2\" << endl;\n}\ncatch (float) { //float型异常的处理代码\n cout << \"A float exception occurred!--from f2\" << endl;\n}\ncout << \"End of f2\" << endl;\n}\n```\n\n仅需说明是否允许抛出异常,有异常未处理,则立即调用 std::terminate\n\n## 异常重新抛出\n\n```cpp\ncatch (MyException &e) {\ne.setMessage(\"new message\");\nthrow;\n}\n//修改被捕获的异常对象;导致传递到上层函数的MyException类型异常对象的数据成员message中所包含的字符串将变成“new message”\ncatch (MyException e) {\ne.setMessage(\"new message\");\nthrow;\n}\n//修改被捕获异常对象的局部副本;传递到上层函数的MyException类型异常对象并不发生改变。\n```\n\n# 题目\n\n## 1\n\n```cpp\n#include <iostream>\n#include <stdexcept>\nusing namespace std;\n\nclass DerivedException : public runtime_error {\npublic:\n DerivedException() : runtime_error(\"派生类异常\") {}\n const char* what() const noexcept override {\n return \"我是派生类!\";\n }\n};\n\nint main() {\n try {\n throw DerivedException();\n } catch (runtime_error e) {\n cout << e.what() << endl;\n }\n return 0;\n}\n```\n\n输出什么:->\"派生类异常\"\n\n**对象切片(Object Slicing):** 1.当派生类对象被赋值给基类对象时(这里是按值捕获),会发生对象切片。即,只有基类部分被复制,派生类的部分被“切掉”。 2.因此,e 是一个 runtime_error 对象,而不是 DerivedException 对象。\n3.e.what() 调用的是 runtime_error 的 what() 方法,而不是 DerivedException 的 what() 方法。\n\n## 2\n\nstd::abort() 和 std::terminate() 都是用于异常终止程序的函数\n简单粗暴 → abort()。\n与异常系统集成 → terminate()\n\n## 3\n\n1.**构造函数中的异常:**\n\n如果构造函数抛出异常,对象被视为未完全构造。\n\nC++ 会自动调用已构造的成员变量和基类的析构函数(栈展开的一部分),但不会调用当前类的析构函数(因为对象未完全构造)。\n\n2.**析构函数的调用规则:**\n\n只有完全构造的对象才会在离开作用域时调用析构函数。\n\n对于部分构造的对象,已成功构造的子对象(成员变量、基类)会被析构,但当前对象的析构函数不会执行。\n\n3.**动态内存的释放:**\n\n如果构造函数中动态分配了内存(如 new),但随后抛出异常,已分配的内存不会自动释放(除非使用智能指针或手动释放)。\n\n需要手动管理或在异常处理中释放资源。\n","source":"_posts/C++1.md","raw":"---\ntitle: 异常处理\ntags: C++\ntop_img: transparent\ncomments: false\n---\n\n# 异常处理概述\n\n## 程序终止\n\n1.执行正常结束而终止\n\n2.程序执行中发生错误或特殊事件而终止(异常终止)\n• 可预测的错误\n• 用户自己定义的错误\n• 难以预测的错误\n\n## 异常处理(exception handling)机制的基本思想\n\n• 采用结构化方法对程序的运行时错误进行**显式管理**:\n\n1.处理的是可预料的错误或特殊事件 2.将程序中的正常处理代码与异常处理代码显式区别开来,提高程序的可\n读性\n\n## C++语言中的异常处理\n\n抛出**异常与异常处理**分离的实现\n\n<font color=red>**Try-Catch 执行机制**</font>\n\n• 若程序有异常,则通过 throw 关键字创建一个异常对象,并抛出\n\n• 将可能抛出异常的程序段嵌在 try 块保护段之中,控制通过正常的顺序执行到达 try 块,然后执行 try 子块内的保护段\n\n• 如果在保护段执行期间没有引发异常,那么跟在 try 子块后的 catch 子句就不执行。\n程序继续执行紧跟在 try 块中最后一个 catch 子句后面的语句\n\n• 如果有异常,catch 子句按其在 try 块后出现的顺序被检查。类型匹配的 catch 子句将捕获并处理异常(或继续抛出异常)\n\n• 如果找不到匹配的处理代码,则自动调用标准库函数 terminate,其默认功能是调用 abort( )终止程序\n\n# 异常定义与抛出\n\n## throw 关键字\n\n```\nthrow 表达式; (1)\nthrow; (2)用于当前异常再抛出\n```\n\n• 表达式可以是任意类型的对象\n\n• throw 表达式; 操作的基本行为:\n\n1. 复制被抛出的对象为临时对象,作为异常对象\n2. 如果在当前函数 try 块中,则中止 try 执行,执行 catch 语句捕获\n3. 如有异常对象未在当前函数被捕获处理,则中止函数执行,异常传播给调用者处理\n\n例:\n\n```cpp\n#include <cstdio>\n#include <cerrno>\nint main () {\nFILE * pf;\ntry {\npf = fopen (\"unexist.txt\", \"rb\");\nif (pf == NULL) throw errno;\n// write something;\nfclose (pf);\n}\ncatch (int errnum) {\nif (errnum!=2) fclose (pf);\nelse perror(\"unexist.txt\");\n}\nreturn 0;\n}\n```\n\n## 异常基类 exception\n\n```cpp\nclass exception {\npublic:\nexception () noexcept;\nexception (const exception&) noexcept;\nexception& operator= (const exception&) noexcept;\nvirtual ~exception();\nvirtual const char* what() const noexcept;\n}\n```\n\n```cpp\n// bad_alloc example\n#include <iostream> // std::cout\n#include <new> // std::bad_alloc\nint main () {\ntry\n{\nint* myarray= new int[10000];\n}\ncatch (std::bad_alloc& ba)\n{\nstd::cerr << \"bad_alloc caught: \" << ba.what() << '\\n';\n}\nreturn 0;\n}\n```\n\n```cpp\n// out_of_range example\n#include <iostream> // std::cerr\n#include <stdexcept> // std::out_of_range\n#include <vector> // std::vector\nint main (void) {\nstd::vector<int> myvector(10);\ntry {\nmyvector.at(20)=100; // vector::at throws an out-of-range\n}\ncatch (const std::out_of_range& oor) {\nstd::cerr << \"Out of Range error: \" << oor.what() << '\\n';\n}\nreturn 0;\n}\n```\n\n# 异常的捕获及处理\n\n异常处理语法结构\n\n```cpp\ntry {\nprogram-statements //程序的正常处理逻辑\nthrow exception-object\nprogram-statements //程序的正常处理逻辑\n…\n}\ncatch (exception-declaration) {\nhandler-statements //异常处理代码\n}\ncatch (exception-declaration) {\nhandler-statements //异常处理代码\n}\n…\ncatch (…) {\nhandler-statements //异常处理代码\n}\n```\n\n## 异常捕获的匹配规则\n\n1.try 期间发生异常; 2.按 catch 顺序与异常定义匹配\n异常对象类型是定义类型或是定义类型的子类\n• 匹配成功\n• 异常接收变量是值,复制异常到接收变量\n• 异常接收变量是引用或指针,创建引用和指针\n• 清除当前异常,执行该异常处理块 3.直到匹配成功或结束\n**要点:**\n• <font color=red>**子类必须优先基类 catch,(…)必须是最后 catch**</font>\n• 用**基类引用类型捕捉异常,且虚函数才能产生多态**\n\n## 异常传播\n\n• 从异常抛出到控制转移给合适的异常处理语句的过程就叫做异常传播。\n\n• 异常传播过程(<font color=red>**一句话:当前函数未处理异常,则交给调用函数**</font>):\n\n1.由里层向外层的执行每一个包围抛出点(异常被抛出的最初位置)的 try 语句。 2.如果当前的成员函数调用中没能定位异常处理,则调用终止。并且在该成员函数调用点将该异常抛给调用者,重复执行上一步。 3.如果该异常终止了当前线程或进程的所有成员函数调用,则说明该线程或进程中不存在对异常的处理,它将自行终止。\n\n## 限定函数异常\n\n```cpp\nvoid f3(int x) throw(double,float) {\nswitch (x) {\ncase 1: throw 3.4; // 抛出double型异常\n case 2: throw 2.5f; // 抛出float型异常\n case 3: throw 1; // 抛出int型异常\n case 5: throw exception(); //抛出标准异常\n }\ncout << \"End of f3\" << endl;\n}\n```\n\n## noexcept 关键字\n\n```cpp\nvoid f2(int x) noexcept {\ntry {\nf3(x);\n}\ncatch (int) { //int型异常的处理代码\n cout << \"An int exception occurred!--from f2\" << endl;\n}\ncatch (float) { //float型异常的处理代码\n cout << \"A float exception occurred!--from f2\" << endl;\n}\ncout << \"End of f2\" << endl;\n}\n```\n\n仅需说明是否允许抛出异常,有异常未处理,则立即调用 std::terminate\n\n## 异常重新抛出\n\n```cpp\ncatch (MyException &e) {\ne.setMessage(\"new message\");\nthrow;\n}\n//修改被捕获的异常对象;导致传递到上层函数的MyException类型异常对象的数据成员message中所包含的字符串将变成“new message”\ncatch (MyException e) {\ne.setMessage(\"new message\");\nthrow;\n}\n//修改被捕获异常对象的局部副本;传递到上层函数的MyException类型异常对象并不发生改变。\n```\n\n# 题目\n\n## 1\n\n```cpp\n#include <iostream>\n#include <stdexcept>\nusing namespace std;\n\nclass DerivedException : public runtime_error {\npublic:\n DerivedException() : runtime_error(\"派生类异常\") {}\n const char* what() const noexcept override {\n return \"我是派生类!\";\n }\n};\n\nint main() {\n try {\n throw DerivedException();\n } catch (runtime_error e) {\n cout << e.what() << endl;\n }\n return 0;\n}\n```\n\n输出什么:->\"派生类异常\"\n\n**对象切片(Object Slicing):** 1.当派生类对象被赋值给基类对象时(这里是按值捕获),会发生对象切片。即,只有基类部分被复制,派生类的部分被“切掉”。 2.因此,e 是一个 runtime_error 对象,而不是 DerivedException 对象。\n3.e.what() 调用的是 runtime_error 的 what() 方法,而不是 DerivedException 的 what() 方法。\n\n## 2\n\nstd::abort() 和 std::terminate() 都是用于异常终止程序的函数\n简单粗暴 → abort()。\n与异常系统集成 → terminate()\n\n## 3\n\n1.**构造函数中的异常:**\n\n如果构造函数抛出异常,对象被视为未完全构造。\n\nC++ 会自动调用已构造的成员变量和基类的析构函数(栈展开的一部分),但不会调用当前类的析构函数(因为对象未完全构造)。\n\n2.**析构函数的调用规则:**\n\n只有完全构造的对象才会在离开作用域时调用析构函数。\n\n对于部分构造的对象,已成功构造的子对象(成员变量、基类)会被析构,但当前对象的析构函数不会执行。\n\n3.**动态内存的释放:**\n\n如果构造函数中动态分配了内存(如 new),但随后抛出异常,已分配的内存不会自动释放(除非使用智能指针或手动释放)。\n\n需要手动管理或在异常处理中释放资源。\n","slug":"C++1","published":1,"date":"2025-06-17T07:48:12.893Z","updated":"2025-06-17T07:48:59.757Z","layout":"post","photos":[],"_id":"cmkmd8tyx000fcw64d7n5go0s","content":"<link rel=\"stylesheet\" class=\"aplayer-secondary-style-marker\" href=\"\\assets\\css\\APlayer.min.css\"><script src=\"\\assets\\js\\APlayer.min.js\" class=\"aplayer-secondary-script-marker\"></script><h1 id=\"异常处理概述\"><a href=\"#异常处理概述\" class=\"headerlink\" title=\"异常处理概述\"></a>异常处理概述</h1><h2 id=\"程序终止\"><a href=\"#程序终止\" class=\"headerlink\" title=\"程序终止\"></a>程序终止</h2><p>1.执行正常结束而终止</p>\n<p>2.程序执行中发生错误或特殊事件而终止(异常终止)<br>• 可预测的错误<br>• 用户自己定义的错误<br>• 难以预测的错误</p>\n<h2 id=\"异常处理(exception-handling)机制的基本思想\"><a href=\"#异常处理(exception-handling)机制的基本思想\" class=\"headerlink\" title=\"异常处理(exception handling)机制的基本思想\"></a>异常处理(exception handling)机制的基本思想</h2><p>• 采用结构化方法对程序的运行时错误进行<strong>显式管理</strong>:</p>\n<p>1.处理的是可预料的错误或特殊事件 2.将程序中的正常处理代码与异常处理代码显式区别开来,提高程序的可<br>读性</p>\n<h2 id=\"C-语言中的异常处理\"><a href=\"#C-语言中的异常处理\" class=\"headerlink\" title=\"C++语言中的异常处理\"></a>C++语言中的异常处理</h2><p>抛出<strong>异常与异常处理</strong>分离的实现</p>\n<p><font color=red><strong>Try-Catch 执行机制</strong></font></p>\n<p>• 若程序有异常,则通过 throw 关键字创建一个异常对象,并抛出</p>\n<p>• 将可能抛出异常的程序段嵌在 try 块保护段之中,控制通过正常的顺序执行到达 try 块,然后执行 try 子块内的保护段</p>\n<p>• 如果在保护段执行期间没有引发异常,那么跟在 try 子块后的 catch 子句就不执行。<br>程序继续执行紧跟在 try 块中最后一个 catch 子句后面的语句</p>\n<p>• 如果有异常,catch 子句按其在 try 块后出现的顺序被检查。类型匹配的 catch 子句将捕获并处理异常(或继续抛出异常)</p>\n<p>• 如果找不到匹配的处理代码,则自动调用标准库函数 terminate,其默认功能是调用 abort( )终止程序</p>\n<h1 id=\"异常定义与抛出\"><a href=\"#异常定义与抛出\" class=\"headerlink\" title=\"异常定义与抛出\"></a>异常定义与抛出</h1><h2 id=\"throw-关键字\"><a href=\"#throw-关键字\" class=\"headerlink\" title=\"throw 关键字\"></a>throw 关键字</h2><figure class=\"highlight actionscript\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">throw</span> 表达式; (<span class=\"number\">1</span>)</span><br><span class=\"line\"><span class=\"keyword\">throw</span>; (<span class=\"number\">2</span>)用于当前异常再抛出</span><br></pre></td></tr></table></figure>\n\n<p>• 表达式可以是任意类型的对象</p>\n<p>• throw 表达式; 操作的基本行为:</p>\n<ol>\n<li>复制被抛出的对象为临时对象,作为异常对象</li>\n<li>如果在当前函数 try 块中,则中止 try 执行,执行 catch 语句捕获</li>\n<li>如有异常对象未在当前函数被捕获处理,则中止函数执行,异常传播给调用者处理</li>\n</ol>\n<p>例:</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span> <span class=\"string\"><cstdio></span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span> <span class=\"string\"><cerrno></span></span></span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span> <span class=\"params\">()</span> </span>{</span><br><span class=\"line\">FILE * pf;</span><br><span class=\"line\"><span class=\"keyword\">try</span> {</span><br><span class=\"line\">pf = <span class=\"built_in\">fopen</span> (<span class=\"string\">"unexist.txt"</span>, <span class=\"string\">"rb"</span>);</span><br><span class=\"line\"><span class=\"keyword\">if</span> (pf == <span class=\"literal\">NULL</span>) <span class=\"keyword\">throw</span> errno;</span><br><span class=\"line\"><span class=\"comment\">// write something;</span></span><br><span class=\"line\"><span class=\"built_in\">fclose</span> (pf);</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"built_in\">catch</span> (<span class=\"type\">int</span> errnum) {</span><br><span class=\"line\"><span class=\"keyword\">if</span> (errnum!=<span class=\"number\">2</span>) <span class=\"built_in\">fclose</span> (pf);</span><br><span class=\"line\"><span class=\"keyword\">else</span> <span class=\"built_in\">perror</span>(<span class=\"string\">"unexist.txt"</span>);</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"keyword\">return</span> <span class=\"number\">0</span>;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<h2 id=\"异常基类-exception\"><a href=\"#异常基类-exception\" class=\"headerlink\" title=\"异常基类 exception\"></a>异常基类 exception</h2><figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">class</span> <span class=\"title class_\">exception</span> {</span><br><span class=\"line\"><span class=\"keyword\">public</span>:</span><br><span class=\"line\"><span class=\"built_in\">exception</span> () <span class=\"keyword\">noexcept</span>;</span><br><span class=\"line\"><span class=\"built_in\">exception</span> (<span class=\"type\">const</span> exception&) <span class=\"keyword\">noexcept</span>;</span><br><span class=\"line\">exception& <span class=\"keyword\">operator</span>= (<span class=\"type\">const</span> exception&) <span class=\"keyword\">noexcept</span>;</span><br><span class=\"line\"><span class=\"keyword\">virtual</span> ~<span class=\"built_in\">exception</span>();</span><br><span class=\"line\"><span class=\"function\"><span class=\"keyword\">virtual</span> <span class=\"type\">const</span> <span class=\"type\">char</span>* <span class=\"title\">what</span><span class=\"params\">()</span> <span class=\"type\">const</span> <span class=\"keyword\">noexcept</span></span>;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">// bad_alloc example</span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span> <span class=\"string\"><iostream></span> <span class=\"comment\">// std::cout</span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span> <span class=\"string\"><new></span> <span class=\"comment\">// std::bad_alloc</span></span></span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span> <span class=\"params\">()</span> </span>{</span><br><span class=\"line\"><span class=\"keyword\">try</span></span><br><span class=\"line\">{</span><br><span class=\"line\"><span class=\"type\">int</span>* myarray= <span class=\"keyword\">new</span> <span class=\"type\">int</span>[<span class=\"number\">10000</span>];</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"built_in\">catch</span> (std::bad_alloc& ba)</span><br><span class=\"line\">{</span><br><span class=\"line\">std::cerr << <span class=\"string\">"bad_alloc caught: "</span> << ba.<span class=\"built_in\">what</span>() << <span class=\"string\">'\\n'</span>;</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"keyword\">return</span> <span class=\"number\">0</span>;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">// out_of_range example</span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span> <span class=\"string\"><iostream></span> <span class=\"comment\">// std::cerr</span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span> <span class=\"string\"><stdexcept></span> <span class=\"comment\">// std::out_of_range</span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span> <span class=\"string\"><vector></span> <span class=\"comment\">// std::vector</span></span></span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span> <span class=\"params\">(<span class=\"type\">void</span>)</span> </span>{</span><br><span class=\"line\"><span class=\"function\">std::vector<<span class=\"type\">int</span>> <span class=\"title\">myvector</span><span class=\"params\">(<span class=\"number\">10</span>)</span></span>;</span><br><span class=\"line\"><span class=\"keyword\">try</span> {</span><br><span class=\"line\">myvector.<span class=\"built_in\">at</span>(<span class=\"number\">20</span>)=<span class=\"number\">100</span>; <span class=\"comment\">// vector::at throws an out-of-range</span></span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"built_in\">catch</span> (<span class=\"type\">const</span> std::out_of_range& oor) {</span><br><span class=\"line\">std::cerr << <span class=\"string\">"Out of Range error: "</span> << oor.<span class=\"built_in\">what</span>() << <span class=\"string\">'\\n'</span>;</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"keyword\">return</span> <span class=\"number\">0</span>;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<h1 id=\"异常的捕获及处理\"><a href=\"#异常的捕获及处理\" class=\"headerlink\" title=\"异常的捕获及处理\"></a>异常的捕获及处理</h1><p>异常处理语法结构</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">try</span> {</span><br><span class=\"line\">program-statements <span class=\"comment\">//程序的正常处理逻辑</span></span><br><span class=\"line\"><span class=\"keyword\">throw</span> exception-object</span><br><span class=\"line\">program-statements <span class=\"comment\">//程序的正常处理逻辑</span></span><br><span class=\"line\">…</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"built_in\">catch</span> (exception-declaration) {</span><br><span class=\"line\">handler-statements <span class=\"comment\">//异常处理代码</span></span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"built_in\">catch</span> (exception-declaration) {</span><br><span class=\"line\">handler-statements <span class=\"comment\">//异常处理代码</span></span><br><span class=\"line\">}</span><br><span class=\"line\">…</span><br><span class=\"line\"><span class=\"built_in\">catch</span> (…) {</span><br><span class=\"line\">handler-statements <span class=\"comment\">//异常处理代码</span></span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<h2 id=\"异常捕获的匹配规则\"><a href=\"#异常捕获的匹配规则\" class=\"headerlink\" title=\"异常捕获的匹配规则\"></a>异常捕获的匹配规则</h2><p>1.try 期间发生异常; 2.按 catch 顺序与异常定义匹配<br>异常对象类型是定义类型或是定义类型的子类<br>• 匹配成功<br>• 异常接收变量是值,复制异常到接收变量<br>• 异常接收变量是引用或指针,创建引用和指针<br>• 清除当前异常,执行该异常处理块 3.直到匹配成功或结束<br><strong>要点:</strong><br>• <font color=red><strong>子类必须优先基类 catch,(…)必须是最后 catch</strong></font><br>• 用<strong>基类引用类型捕捉异常,且虚函数才能产生多态</strong></p>\n<h2 id=\"异常传播\"><a href=\"#异常传播\" class=\"headerlink\" title=\"异常传播\"></a>异常传播</h2><p>• 从异常抛出到控制转移给合适的异常处理语句的过程就叫做异常传播。</p>\n<p>• 异常传播过程(<font color=red><strong>一句话:当前函数未处理异常,则交给调用函数</strong></font>):</p>\n<p>1.由里层向外层的执行每一个包围抛出点(异常被抛出的最初位置)的 try 语句。 2.如果当前的成员函数调用中没能定位异常处理,则调用终止。并且在该成员函数调用点将该异常抛给调用者,重复执行上一步。 3.如果该异常终止了当前线程或进程的所有成员函数调用,则说明该线程或进程中不存在对异常的处理,它将自行终止。</p>\n<h2 id=\"限定函数异常\"><a href=\"#限定函数异常\" class=\"headerlink\" title=\"限定函数异常\"></a>限定函数异常</h2><figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"function\"><span class=\"type\">void</span> <span class=\"title\">f3</span><span class=\"params\">(<span class=\"type\">int</span> x)</span> <span class=\"title\">throw</span><span class=\"params\">(<span class=\"type\">double</span>,<span class=\"type\">float</span>)</span> </span>{</span><br><span class=\"line\"><span class=\"keyword\">switch</span> (x) {</span><br><span class=\"line\"><span class=\"keyword\">case</span> <span class=\"number\">1</span>: <span class=\"keyword\">throw</span> <span class=\"number\">3.4</span>; <span class=\"comment\">// 抛出double型异常</span></span><br><span class=\"line\"> <span class=\"keyword\">case</span> <span class=\"number\">2</span>: <span class=\"keyword\">throw</span> <span class=\"number\">2.5f</span>; <span class=\"comment\">// 抛出float型异常</span></span><br><span class=\"line\"> <span class=\"keyword\">case</span> <span class=\"number\">3</span>: <span class=\"keyword\">throw</span> <span class=\"number\">1</span>; <span class=\"comment\">// 抛出int型异常</span></span><br><span class=\"line\"> <span class=\"keyword\">case</span> <span class=\"number\">5</span>: <span class=\"keyword\">throw</span> <span class=\"built_in\">exception</span>(); <span class=\"comment\">//抛出标准异常</span></span><br><span class=\"line\"> }</span><br><span class=\"line\">cout << <span class=\"string\">"End of f3"</span> << endl;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<h2 id=\"noexcept-关键字\"><a href=\"#noexcept-关键字\" class=\"headerlink\" title=\"noexcept 关键字\"></a>noexcept 关键字</h2><figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"function\"><span class=\"type\">void</span> <span class=\"title\">f2</span><span class=\"params\">(<span class=\"type\">int</span> x)</span> <span class=\"keyword\">noexcept</span> </span>{</span><br><span class=\"line\"><span class=\"keyword\">try</span> {</span><br><span class=\"line\"><span class=\"built_in\">f3</span>(x);</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"built_in\">catch</span> (<span class=\"type\">int</span>) { <span class=\"comment\">//int型异常的处理代码</span></span><br><span class=\"line\"> cout << <span class=\"string\">"An int exception occurred!--from f2"</span> << endl;</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"built_in\">catch</span> (<span class=\"type\">float</span>) { <span class=\"comment\">//float型异常的处理代码</span></span><br><span class=\"line\"> cout << <span class=\"string\">"A float exception occurred!--from f2"</span> << endl;</span><br><span class=\"line\">}</span><br><span class=\"line\">cout << <span class=\"string\">"End of f2"</span> << endl;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<p>仅需说明是否允许抛出异常,有异常未处理,则立即调用 std::terminate</p>\n<h2 id=\"异常重新抛出\"><a href=\"#异常重新抛出\" class=\"headerlink\" title=\"异常重新抛出\"></a>异常重新抛出</h2><figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"built_in\">catch</span> (MyException &e) {</span><br><span class=\"line\">e.<span class=\"built_in\">setMessage</span>(<span class=\"string\">"new message"</span>);</span><br><span class=\"line\"><span class=\"keyword\">throw</span>;</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"comment\">//修改被捕获的异常对象;导致传递到上层函数的MyException类型异常对象的数据成员message中所包含的字符串将变成“new message”</span></span><br><span class=\"line\"><span class=\"built_in\">catch</span> (MyException e) {</span><br><span class=\"line\">e.<span class=\"built_in\">setMessage</span>(<span class=\"string\">"new message"</span>);</span><br><span class=\"line\"><span class=\"keyword\">throw</span>;</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"comment\">//修改被捕获异常对象的局部副本;传递到上层函数的MyException类型异常对象并不发生改变。</span></span><br></pre></td></tr></table></figure>\n\n<h1 id=\"题目\"><a href=\"#题目\" class=\"headerlink\" title=\"题目\"></a>题目</h1><h2 id=\"1\"><a href=\"#1\" class=\"headerlink\" title=\"1\"></a>1</h2><figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span> <span class=\"string\"><iostream></span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span> <span class=\"string\"><stdexcept></span></span></span><br><span class=\"line\"><span class=\"keyword\">using</span> <span class=\"keyword\">namespace</span> std;</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">class</span> <span class=\"title class_\">DerivedException</span> : <span class=\"keyword\">public</span> runtime_error {</span><br><span class=\"line\"><span class=\"keyword\">public</span>:</span><br><span class=\"line\"> <span class=\"built_in\">DerivedException</span>() : <span class=\"built_in\">runtime_error</span>(<span class=\"string\">"派生类异常"</span>) {}</span><br><span class=\"line\"> <span class=\"function\"><span class=\"type\">const</span> <span class=\"type\">char</span>* <span class=\"title\">what</span><span class=\"params\">()</span> <span class=\"type\">const</span> <span class=\"keyword\">noexcept</span> <span class=\"keyword\">override</span> </span>{</span><br><span class=\"line\"> <span class=\"keyword\">return</span> <span class=\"string\">"我是派生类!"</span>;</span><br><span class=\"line\"> }</span><br><span class=\"line\">};</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span><span class=\"params\">()</span> </span>{</span><br><span class=\"line\"> <span class=\"keyword\">try</span> {</span><br><span class=\"line\"> <span class=\"keyword\">throw</span> <span class=\"built_in\">DerivedException</span>();</span><br><span class=\"line\"> } <span class=\"built_in\">catch</span> (runtime_error e) {</span><br><span class=\"line\"> cout << e.<span class=\"built_in\">what</span>() << endl;</span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"keyword\">return</span> <span class=\"number\">0</span>;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<p>输出什么:->”派生类异常”</p>\n<p><strong>对象切片(Object Slicing):</strong> 1.当派生类对象被赋值给基类对象时(这里是按值捕获),会发生对象切片。即,只有基类部分被复制,派生类的部分被“切掉”。 2.因此,e 是一个 runtime_error 对象,而不是 DerivedException 对象。<br>3.e.what() 调用的是 runtime_error 的 what() 方法,而不是 DerivedException 的 what() 方法。</p>\n<h2 id=\"2\"><a href=\"#2\" class=\"headerlink\" title=\"2\"></a>2</h2><p>std::abort() 和 std::terminate() 都是用于异常终止程序的函数<br>简单粗暴 → abort()。<br>与异常系统集成 → terminate()</p>\n<h2 id=\"3\"><a href=\"#3\" class=\"headerlink\" title=\"3\"></a>3</h2><p>1.<strong>构造函数中的异常:</strong></p>\n<p>如果构造函数抛出异常,对象被视为未完全构造。</p>\n<p>C++ 会自动调用已构造的成员变量和基类的析构函数(栈展开的一部分),但不会调用当前类的析构函数(因为对象未完全构造)。</p>\n<p>2.<strong>析构函数的调用规则:</strong></p>\n<p>只有完全构造的对象才会在离开作用域时调用析构函数。</p>\n<p>对于部分构造的对象,已成功构造的子对象(成员变量、基类)会被析构,但当前对象的析构函数不会执行。</p>\n<p>3.<strong>动态内存的释放:</strong></p>\n<p>如果构造函数中动态分配了内存(如 new),但随后抛出异常,已分配的内存不会自动释放(除非使用智能指针或手动释放)。</p>\n<p>需要手动管理或在异常处理中释放资源。</p>\n","excerpt":"","more":"<h1 id=\"异常处理概述\"><a href=\"#异常处理概述\" class=\"headerlink\" title=\"异常处理概述\"></a>异常处理概述</h1><h2 id=\"程序终止\"><a href=\"#程序终止\" class=\"headerlink\" title=\"程序终止\"></a>程序终止</h2><p>1.执行正常结束而终止</p>\n<p>2.程序执行中发生错误或特殊事件而终止(异常终止)<br>• 可预测的错误<br>• 用户自己定义的错误<br>• 难以预测的错误</p>\n<h2 id=\"异常处理(exception-handling)机制的基本思想\"><a href=\"#异常处理(exception-handling)机制的基本思想\" class=\"headerlink\" title=\"异常处理(exception handling)机制的基本思想\"></a>异常处理(exception handling)机制的基本思想</h2><p>• 采用结构化方法对程序的运行时错误进行<strong>显式管理</strong>:</p>\n<p>1.处理的是可预料的错误或特殊事件 2.将程序中的正常处理代码与异常处理代码显式区别开来,提高程序的可<br>读性</p>\n<h2 id=\"C-语言中的异常处理\"><a href=\"#C-语言中的异常处理\" class=\"headerlink\" title=\"C++语言中的异常处理\"></a>C++语言中的异常处理</h2><p>抛出<strong>异常与异常处理</strong>分离的实现</p>\n<p><font color=red><strong>Try-Catch 执行机制</strong></font></p>\n<p>• 若程序有异常,则通过 throw 关键字创建一个异常对象,并抛出</p>\n<p>• 将可能抛出异常的程序段嵌在 try 块保护段之中,控制通过正常的顺序执行到达 try 块,然后执行 try 子块内的保护段</p>\n<p>• 如果在保护段执行期间没有引发异常,那么跟在 try 子块后的 catch 子句就不执行。<br>程序继续执行紧跟在 try 块中最后一个 catch 子句后面的语句</p>\n<p>• 如果有异常,catch 子句按其在 try 块后出现的顺序被检查。类型匹配的 catch 子句将捕获并处理异常(或继续抛出异常)</p>\n<p>• 如果找不到匹配的处理代码,则自动调用标准库函数 terminate,其默认功能是调用 abort( )终止程序</p>\n<h1 id=\"异常定义与抛出\"><a href=\"#异常定义与抛出\" class=\"headerlink\" title=\"异常定义与抛出\"></a>异常定义与抛出</h1><h2 id=\"throw-关键字\"><a href=\"#throw-关键字\" class=\"headerlink\" title=\"throw 关键字\"></a>throw 关键字</h2><figure class=\"highlight actionscript\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">throw</span> 表达式; (<span class=\"number\">1</span>)</span><br><span class=\"line\"><span class=\"keyword\">throw</span>; (<span class=\"number\">2</span>)用于当前异常再抛出</span><br></pre></td></tr></table></figure>\n\n<p>• 表达式可以是任意类型的对象</p>\n<p>• throw 表达式; 操作的基本行为:</p>\n<ol>\n<li>复制被抛出的对象为临时对象,作为异常对象</li>\n<li>如果在当前函数 try 块中,则中止 try 执行,执行 catch 语句捕获</li>\n<li>如有异常对象未在当前函数被捕获处理,则中止函数执行,异常传播给调用者处理</li>\n</ol>\n<p>例:</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span> <span class=\"string\"><cstdio></span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span> <span class=\"string\"><cerrno></span></span></span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span> <span class=\"params\">()</span> </span>{</span><br><span class=\"line\">FILE * pf;</span><br><span class=\"line\"><span class=\"keyword\">try</span> {</span><br><span class=\"line\">pf = <span class=\"built_in\">fopen</span> (<span class=\"string\">"unexist.txt"</span>, <span class=\"string\">"rb"</span>);</span><br><span class=\"line\"><span class=\"keyword\">if</span> (pf == <span class=\"literal\">NULL</span>) <span class=\"keyword\">throw</span> errno;</span><br><span class=\"line\"><span class=\"comment\">// write something;</span></span><br><span class=\"line\"><span class=\"built_in\">fclose</span> (pf);</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"built_in\">catch</span> (<span class=\"type\">int</span> errnum) {</span><br><span class=\"line\"><span class=\"keyword\">if</span> (errnum!=<span class=\"number\">2</span>) <span class=\"built_in\">fclose</span> (pf);</span><br><span class=\"line\"><span class=\"keyword\">else</span> <span class=\"built_in\">perror</span>(<span class=\"string\">"unexist.txt"</span>);</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"keyword\">return</span> <span class=\"number\">0</span>;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<h2 id=\"异常基类-exception\"><a href=\"#异常基类-exception\" class=\"headerlink\" title=\"异常基类 exception\"></a>异常基类 exception</h2><figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">class</span> <span class=\"title class_\">exception</span> {</span><br><span class=\"line\"><span class=\"keyword\">public</span>:</span><br><span class=\"line\"><span class=\"built_in\">exception</span> () <span class=\"keyword\">noexcept</span>;</span><br><span class=\"line\"><span class=\"built_in\">exception</span> (<span class=\"type\">const</span> exception&) <span class=\"keyword\">noexcept</span>;</span><br><span class=\"line\">exception& <span class=\"keyword\">operator</span>= (<span class=\"type\">const</span> exception&) <span class=\"keyword\">noexcept</span>;</span><br><span class=\"line\"><span class=\"keyword\">virtual</span> ~<span class=\"built_in\">exception</span>();</span><br><span class=\"line\"><span class=\"function\"><span class=\"keyword\">virtual</span> <span class=\"type\">const</span> <span class=\"type\">char</span>* <span class=\"title\">what</span><span class=\"params\">()</span> <span class=\"type\">const</span> <span class=\"keyword\">noexcept</span></span>;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">// bad_alloc example</span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span> <span class=\"string\"><iostream></span> <span class=\"comment\">// std::cout</span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span> <span class=\"string\"><new></span> <span class=\"comment\">// std::bad_alloc</span></span></span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span> <span class=\"params\">()</span> </span>{</span><br><span class=\"line\"><span class=\"keyword\">try</span></span><br><span class=\"line\">{</span><br><span class=\"line\"><span class=\"type\">int</span>* myarray= <span class=\"keyword\">new</span> <span class=\"type\">int</span>[<span class=\"number\">10000</span>];</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"built_in\">catch</span> (std::bad_alloc& ba)</span><br><span class=\"line\">{</span><br><span class=\"line\">std::cerr << <span class=\"string\">"bad_alloc caught: "</span> << ba.<span class=\"built_in\">what</span>() << <span class=\"string\">'\\n'</span>;</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"keyword\">return</span> <span class=\"number\">0</span>;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">// out_of_range example</span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span> <span class=\"string\"><iostream></span> <span class=\"comment\">// std::cerr</span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span> <span class=\"string\"><stdexcept></span> <span class=\"comment\">// std::out_of_range</span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span> <span class=\"string\"><vector></span> <span class=\"comment\">// std::vector</span></span></span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span> <span class=\"params\">(<span class=\"type\">void</span>)</span> </span>{</span><br><span class=\"line\"><span class=\"function\">std::vector<<span class=\"type\">int</span>> <span class=\"title\">myvector</span><span class=\"params\">(<span class=\"number\">10</span>)</span></span>;</span><br><span class=\"line\"><span class=\"keyword\">try</span> {</span><br><span class=\"line\">myvector.<span class=\"built_in\">at</span>(<span class=\"number\">20</span>)=<span class=\"number\">100</span>; <span class=\"comment\">// vector::at throws an out-of-range</span></span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"built_in\">catch</span> (<span class=\"type\">const</span> std::out_of_range& oor) {</span><br><span class=\"line\">std::cerr << <span class=\"string\">"Out of Range error: "</span> << oor.<span class=\"built_in\">what</span>() << <span class=\"string\">'\\n'</span>;</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"keyword\">return</span> <span class=\"number\">0</span>;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<h1 id=\"异常的捕获及处理\"><a href=\"#异常的捕获及处理\" class=\"headerlink\" title=\"异常的捕获及处理\"></a>异常的捕获及处理</h1><p>异常处理语法结构</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">try</span> {</span><br><span class=\"line\">program-statements <span class=\"comment\">//程序的正常处理逻辑</span></span><br><span class=\"line\"><span class=\"keyword\">throw</span> exception-object</span><br><span class=\"line\">program-statements <span class=\"comment\">//程序的正常处理逻辑</span></span><br><span class=\"line\">…</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"built_in\">catch</span> (exception-declaration) {</span><br><span class=\"line\">handler-statements <span class=\"comment\">//异常处理代码</span></span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"built_in\">catch</span> (exception-declaration) {</span><br><span class=\"line\">handler-statements <span class=\"comment\">//异常处理代码</span></span><br><span class=\"line\">}</span><br><span class=\"line\">…</span><br><span class=\"line\"><span class=\"built_in\">catch</span> (…) {</span><br><span class=\"line\">handler-statements <span class=\"comment\">//异常处理代码</span></span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<h2 id=\"异常捕获的匹配规则\"><a href=\"#异常捕获的匹配规则\" class=\"headerlink\" title=\"异常捕获的匹配规则\"></a>异常捕获的匹配规则</h2><p>1.try 期间发生异常; 2.按 catch 顺序与异常定义匹配<br>异常对象类型是定义类型或是定义类型的子类<br>• 匹配成功<br>• 异常接收变量是值,复制异常到接收变量<br>• 异常接收变量是引用或指针,创建引用和指针<br>• 清除当前异常,执行该异常处理块 3.直到匹配成功或结束<br><strong>要点:</strong><br>• <font color=red><strong>子类必须优先基类 catch,(…)必须是最后 catch</strong></font><br>• 用<strong>基类引用类型捕捉异常,且虚函数才能产生多态</strong></p>\n<h2 id=\"异常传播\"><a href=\"#异常传播\" class=\"headerlink\" title=\"异常传播\"></a>异常传播</h2><p>• 从异常抛出到控制转移给合适的异常处理语句的过程就叫做异常传播。</p>\n<p>• 异常传播过程(<font color=red><strong>一句话:当前函数未处理异常,则交给调用函数</strong></font>):</p>\n<p>1.由里层向外层的执行每一个包围抛出点(异常被抛出的最初位置)的 try 语句。 2.如果当前的成员函数调用中没能定位异常处理,则调用终止。并且在该成员函数调用点将该异常抛给调用者,重复执行上一步。 3.如果该异常终止了当前线程或进程的所有成员函数调用,则说明该线程或进程中不存在对异常的处理,它将自行终止。</p>\n<h2 id=\"限定函数异常\"><a href=\"#限定函数异常\" class=\"headerlink\" title=\"限定函数异常\"></a>限定函数异常</h2><figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"function\"><span class=\"type\">void</span> <span class=\"title\">f3</span><span class=\"params\">(<span class=\"type\">int</span> x)</span> <span class=\"title\">throw</span><span class=\"params\">(<span class=\"type\">double</span>,<span class=\"type\">float</span>)</span> </span>{</span><br><span class=\"line\"><span class=\"keyword\">switch</span> (x) {</span><br><span class=\"line\"><span class=\"keyword\">case</span> <span class=\"number\">1</span>: <span class=\"keyword\">throw</span> <span class=\"number\">3.4</span>; <span class=\"comment\">// 抛出double型异常</span></span><br><span class=\"line\"> <span class=\"keyword\">case</span> <span class=\"number\">2</span>: <span class=\"keyword\">throw</span> <span class=\"number\">2.5f</span>; <span class=\"comment\">// 抛出float型异常</span></span><br><span class=\"line\"> <span class=\"keyword\">case</span> <span class=\"number\">3</span>: <span class=\"keyword\">throw</span> <span class=\"number\">1</span>; <span class=\"comment\">// 抛出int型异常</span></span><br><span class=\"line\"> <span class=\"keyword\">case</span> <span class=\"number\">5</span>: <span class=\"keyword\">throw</span> <span class=\"built_in\">exception</span>(); <span class=\"comment\">//抛出标准异常</span></span><br><span class=\"line\"> }</span><br><span class=\"line\">cout << <span class=\"string\">"End of f3"</span> << endl;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<h2 id=\"noexcept-关键字\"><a href=\"#noexcept-关键字\" class=\"headerlink\" title=\"noexcept 关键字\"></a>noexcept 关键字</h2><figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"function\"><span class=\"type\">void</span> <span class=\"title\">f2</span><span class=\"params\">(<span class=\"type\">int</span> x)</span> <span class=\"keyword\">noexcept</span> </span>{</span><br><span class=\"line\"><span class=\"keyword\">try</span> {</span><br><span class=\"line\"><span class=\"built_in\">f3</span>(x);</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"built_in\">catch</span> (<span class=\"type\">int</span>) { <span class=\"comment\">//int型异常的处理代码</span></span><br><span class=\"line\"> cout << <span class=\"string\">"An int exception occurred!--from f2"</span> << endl;</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"built_in\">catch</span> (<span class=\"type\">float</span>) { <span class=\"comment\">//float型异常的处理代码</span></span><br><span class=\"line\"> cout << <span class=\"string\">"A float exception occurred!--from f2"</span> << endl;</span><br><span class=\"line\">}</span><br><span class=\"line\">cout << <span class=\"string\">"End of f2"</span> << endl;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<p>仅需说明是否允许抛出异常,有异常未处理,则立即调用 std::terminate</p>\n<h2 id=\"异常重新抛出\"><a href=\"#异常重新抛出\" class=\"headerlink\" title=\"异常重新抛出\"></a>异常重新抛出</h2><figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"built_in\">catch</span> (MyException &e) {</span><br><span class=\"line\">e.<span class=\"built_in\">setMessage</span>(<span class=\"string\">"new message"</span>);</span><br><span class=\"line\"><span class=\"keyword\">throw</span>;</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"comment\">//修改被捕获的异常对象;导致传递到上层函数的MyException类型异常对象的数据成员message中所包含的字符串将变成“new message”</span></span><br><span class=\"line\"><span class=\"built_in\">catch</span> (MyException e) {</span><br><span class=\"line\">e.<span class=\"built_in\">setMessage</span>(<span class=\"string\">"new message"</span>);</span><br><span class=\"line\"><span class=\"keyword\">throw</span>;</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"comment\">//修改被捕获异常对象的局部副本;传递到上层函数的MyException类型异常对象并不发生改变。</span></span><br></pre></td></tr></table></figure>\n\n<h1 id=\"题目\"><a href=\"#题目\" class=\"headerlink\" title=\"题目\"></a>题目</h1><h2 id=\"1\"><a href=\"#1\" class=\"headerlink\" title=\"1\"></a>1</h2><figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span> <span class=\"string\"><iostream></span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span> <span class=\"string\"><stdexcept></span></span></span><br><span class=\"line\"><span class=\"keyword\">using</span> <span class=\"keyword\">namespace</span> std;</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">class</span> <span class=\"title class_\">DerivedException</span> : <span class=\"keyword\">public</span> runtime_error {</span><br><span class=\"line\"><span class=\"keyword\">public</span>:</span><br><span class=\"line\"> <span class=\"built_in\">DerivedException</span>() : <span class=\"built_in\">runtime_error</span>(<span class=\"string\">"派生类异常"</span>) {}</span><br><span class=\"line\"> <span class=\"function\"><span class=\"type\">const</span> <span class=\"type\">char</span>* <span class=\"title\">what</span><span class=\"params\">()</span> <span class=\"type\">const</span> <span class=\"keyword\">noexcept</span> <span class=\"keyword\">override</span> </span>{</span><br><span class=\"line\"> <span class=\"keyword\">return</span> <span class=\"string\">"我是派生类!"</span>;</span><br><span class=\"line\"> }</span><br><span class=\"line\">};</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span><span class=\"params\">()</span> </span>{</span><br><span class=\"line\"> <span class=\"keyword\">try</span> {</span><br><span class=\"line\"> <span class=\"keyword\">throw</span> <span class=\"built_in\">DerivedException</span>();</span><br><span class=\"line\"> } <span class=\"built_in\">catch</span> (runtime_error e) {</span><br><span class=\"line\"> cout << e.<span class=\"built_in\">what</span>() << endl;</span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"keyword\">return</span> <span class=\"number\">0</span>;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<p>输出什么:->”派生类异常”</p>\n<p><strong>对象切片(Object Slicing):</strong> 1.当派生类对象被赋值给基类对象时(这里是按值捕获),会发生对象切片。即,只有基类部分被复制,派生类的部分被“切掉”。 2.因此,e 是一个 runtime_error 对象,而不是 DerivedException 对象。<br>3.e.what() 调用的是 runtime_error 的 what() 方法,而不是 DerivedException 的 what() 方法。</p>\n<h2 id=\"2\"><a href=\"#2\" class=\"headerlink\" title=\"2\"></a>2</h2><p>std::abort() 和 std::terminate() 都是用于异常终止程序的函数<br>简单粗暴 → abort()。<br>与异常系统集成 → terminate()</p>\n<h2 id=\"3\"><a href=\"#3\" class=\"headerlink\" title=\"3\"></a>3</h2><p>1.<strong>构造函数中的异常:</strong></p>\n<p>如果构造函数抛出异常,对象被视为未完全构造。</p>\n<p>C++ 会自动调用已构造的成员变量和基类的析构函数(栈展开的一部分),但不会调用当前类的析构函数(因为对象未完全构造)。</p>\n<p>2.<strong>析构函数的调用规则:</strong></p>\n<p>只有完全构造的对象才会在离开作用域时调用析构函数。</p>\n<p>对于部分构造的对象,已成功构造的子对象(成员变量、基类)会被析构,但当前对象的析构函数不会执行。</p>\n<p>3.<strong>动态内存的释放:</strong></p>\n<p>如果构造函数中动态分配了内存(如 new),但随后抛出异常,已分配的内存不会自动释放(除非使用智能指针或手动释放)。</p>\n<p>需要手动管理或在异常处理中释放资源。</p>\n"},{"title":"继承和派生","top_img":"transparent","comments":0,"_content":"\n# 继承/派生的概念\n\n当定义一个新的类 B 时,如果发现类 B 拥有某个已写好的类 A 的全部特点,此外还有类 A 没有的特点,那么就不必从头重写类 B,而是可以把类 A 作为一个“基类”(也称“父类”),把类 B 写为基类 A 的一个“派生类”(也称“子类”)。这样,就可以说从类 A “派生”出了类 B,也可以说类 B “继承”了类 A。\n\n派生类是通过对基类进行扩充和修改得到的。基类的所有成员自动成为派生类的成员。\n\n# 语法与访问控制\n\n```cpp\nclass 派生类名:继承访问控制 基类类名{\n成员访问控制:\n 成员声明列表;\n };\n```\n\n继承访问控制和成员访问控制均由保留 public、protected、private 来定义,缺省均为 private。\n`private(私有的)`\n`public (公有的)`\n`protected(受保护的)`\n\n| 基类中成员的访问控制 | 继承访问控制 | 派生类中继承成员的访问控制 |\n| -------------------- | ------------ | -------------------------- |\n| public | public | public |\n| protected | | protected |\n| private | | 不可访问 |\n| public | protected | protected |\n| protected | | protected |\n| private | | 不可访问 |\n| public | private | private |\n| protected | | private |\n| private | | 不可访问 |\n\n# 构造与析构顺序\n\n# 派生与构造函数\n\n# 派生与成员函数\n\n# 改变访问控制\n\n# 类型兼容性\n\n# 类的类型转换\n\n# 多重继承\n","source":"_posts/ninth-blog.md","raw":"---\ntitle: 继承和派生\ntags: C++\ntop_img: transparent\ncomments: false\n---\n\n# 继承/派生的概念\n\n当定义一个新的类 B 时,如果发现类 B 拥有某个已写好的类 A 的全部特点,此外还有类 A 没有的特点,那么就不必从头重写类 B,而是可以把类 A 作为一个“基类”(也称“父类”),把类 B 写为基类 A 的一个“派生类”(也称“子类”)。这样,就可以说从类 A “派生”出了类 B,也可以说类 B “继承”了类 A。\n\n派生类是通过对基类进行扩充和修改得到的。基类的所有成员自动成为派生类的成员。\n\n# 语法与访问控制\n\n```cpp\nclass 派生类名:继承访问控制 基类类名{\n成员访问控制:\n 成员声明列表;\n };\n```\n\n继承访问控制和成员访问控制均由保留 public、protected、private 来定义,缺省均为 private。\n`private(私有的)`\n`public (公有的)`\n`protected(受保护的)`\n\n| 基类中成员的访问控制 | 继承访问控制 | 派生类中继承成员的访问控制 |\n| -------------------- | ------------ | -------------------------- |\n| public | public | public |\n| protected | | protected |\n| private | | 不可访问 |\n| public | protected | protected |\n| protected | | protected |\n| private | | 不可访问 |\n| public | private | private |\n| protected | | private |\n| private | | 不可访问 |\n\n# 构造与析构顺序\n\n# 派生与构造函数\n\n# 派生与成员函数\n\n# 改变访问控制\n\n# 类型兼容性\n\n# 类的类型转换\n\n# 多重继承\n","slug":"ninth-blog","published":1,"date":"2025-05-08T06:48:07.262Z","updated":"2025-05-08T07:05:05.729Z","layout":"post","photos":[],"_id":"cmkmd8tyy000gcw64cugdd8we","content":"<link rel=\"stylesheet\" class=\"aplayer-secondary-style-marker\" href=\"\\assets\\css\\APlayer.min.css\"><script src=\"\\assets\\js\\APlayer.min.js\" class=\"aplayer-secondary-script-marker\"></script><h1 id=\"继承-派生的概念\"><a href=\"#继承-派生的概念\" class=\"headerlink\" title=\"继承/派生的概念\"></a>继承/派生的概念</h1><p>当定义一个新的类 B 时,如果发现类 B 拥有某个已写好的类 A 的全部特点,此外还有类 A 没有的特点,那么就不必从头重写类 B,而是可以把类 A 作为一个“基类”(也称“父类”),把类 B 写为基类 A 的一个“派生类”(也称“子类”)。这样,就可以说从类 A “派生”出了类 B,也可以说类 B “继承”了类 A。</p>\n<p>派生类是通过对基类进行扩充和修改得到的。基类的所有成员自动成为派生类的成员。</p>\n<h1 id=\"语法与访问控制\"><a href=\"#语法与访问控制\" class=\"headerlink\" title=\"语法与访问控制\"></a>语法与访问控制</h1><figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">class</span> 派生类名:继承访问控制 基类类名{</span><br><span class=\"line\">成员访问控制:</span><br><span class=\"line\"> 成员声明列表;</span><br><span class=\"line\"> };</span><br></pre></td></tr></table></figure>\n\n<p>继承访问控制和成员访问控制均由保留 public、protected、private 来定义,缺省均为 private。<br><code>private(私有的)</code><br><code>public (公有的)</code><br><code>protected(受保护的)</code></p>\n<table>\n<thead>\n<tr>\n<th>基类中成员的访问控制</th>\n<th>继承访问控制</th>\n<th>派生类中继承成员的访问控制</th>\n</tr>\n</thead>\n<tbody><tr>\n<td>public</td>\n<td>public</td>\n<td>public</td>\n</tr>\n<tr>\n<td>protected</td>\n<td></td>\n<td>protected</td>\n</tr>\n<tr>\n<td>private</td>\n<td></td>\n<td>不可访问</td>\n</tr>\n<tr>\n<td>public</td>\n<td>protected</td>\n<td>protected</td>\n</tr>\n<tr>\n<td>protected</td>\n<td></td>\n<td>protected</td>\n</tr>\n<tr>\n<td>private</td>\n<td></td>\n<td>不可访问</td>\n</tr>\n<tr>\n<td>public</td>\n<td>private</td>\n<td>private</td>\n</tr>\n<tr>\n<td>protected</td>\n<td></td>\n<td>private</td>\n</tr>\n<tr>\n<td>private</td>\n<td></td>\n<td>不可访问</td>\n</tr>\n</tbody></table>\n<h1 id=\"构造与析构顺序\"><a href=\"#构造与析构顺序\" class=\"headerlink\" title=\"构造与析构顺序\"></a>构造与析构顺序</h1><h1 id=\"派生与构造函数\"><a href=\"#派生与构造函数\" class=\"headerlink\" title=\"派生与构造函数\"></a>派生与构造函数</h1><h1 id=\"派生与成员函数\"><a href=\"#派生与成员函数\" class=\"headerlink\" title=\"派生与成员函数\"></a>派生与成员函数</h1><h1 id=\"改变访问控制\"><a href=\"#改变访问控制\" class=\"headerlink\" title=\"改变访问控制\"></a>改变访问控制</h1><h1 id=\"类型兼容性\"><a href=\"#类型兼容性\" class=\"headerlink\" title=\"类型兼容性\"></a>类型兼容性</h1><h1 id=\"类的类型转换\"><a href=\"#类的类型转换\" class=\"headerlink\" title=\"类的类型转换\"></a>类的类型转换</h1><h1 id=\"多重继承\"><a href=\"#多重继承\" class=\"headerlink\" title=\"多重继承\"></a>多重继承</h1>","excerpt":"","more":"<h1 id=\"继承-派生的概念\"><a href=\"#继承-派生的概念\" class=\"headerlink\" title=\"继承/派生的概念\"></a>继承/派生的概念</h1><p>当定义一个新的类 B 时,如果发现类 B 拥有某个已写好的类 A 的全部特点,此外还有类 A 没有的特点,那么就不必从头重写类 B,而是可以把类 A 作为一个“基类”(也称“父类”),把类 B 写为基类 A 的一个“派生类”(也称“子类”)。这样,就可以说从类 A “派生”出了类 B,也可以说类 B “继承”了类 A。</p>\n<p>派生类是通过对基类进行扩充和修改得到的。基类的所有成员自动成为派生类的成员。</p>\n<h1 id=\"语法与访问控制\"><a href=\"#语法与访问控制\" class=\"headerlink\" title=\"语法与访问控制\"></a>语法与访问控制</h1><figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">class</span> 派生类名:继承访问控制 基类类名{</span><br><span class=\"line\">成员访问控制:</span><br><span class=\"line\"> 成员声明列表;</span><br><span class=\"line\"> };</span><br></pre></td></tr></table></figure>\n\n<p>继承访问控制和成员访问控制均由保留 public、protected、private 来定义,缺省均为 private。<br><code>private(私有的)</code><br><code>public (公有的)</code><br><code>protected(受保护的)</code></p>\n<table>\n<thead>\n<tr>\n<th>基类中成员的访问控制</th>\n<th>继承访问控制</th>\n<th>派生类中继承成员的访问控制</th>\n</tr>\n</thead>\n<tbody><tr>\n<td>public</td>\n<td>public</td>\n<td>public</td>\n</tr>\n<tr>\n<td>protected</td>\n<td></td>\n<td>protected</td>\n</tr>\n<tr>\n<td>private</td>\n<td></td>\n<td>不可访问</td>\n</tr>\n<tr>\n<td>public</td>\n<td>protected</td>\n<td>protected</td>\n</tr>\n<tr>\n<td>protected</td>\n<td></td>\n<td>protected</td>\n</tr>\n<tr>\n<td>private</td>\n<td></td>\n<td>不可访问</td>\n</tr>\n<tr>\n<td>public</td>\n<td>private</td>\n<td>private</td>\n</tr>\n<tr>\n<td>protected</td>\n<td></td>\n<td>private</td>\n</tr>\n<tr>\n<td>private</td>\n<td></td>\n<td>不可访问</td>\n</tr>\n</tbody></table>\n<h1 id=\"构造与析构顺序\"><a href=\"#构造与析构顺序\" class=\"headerlink\" title=\"构造与析构顺序\"></a>构造与析构顺序</h1><h1 id=\"派生与构造函数\"><a href=\"#派生与构造函数\" class=\"headerlink\" title=\"派生与构造函数\"></a>派生与构造函数</h1><h1 id=\"派生与成员函数\"><a href=\"#派生与成员函数\" class=\"headerlink\" title=\"派生与成员函数\"></a>派生与成员函数</h1><h1 id=\"改变访问控制\"><a href=\"#改变访问控制\" class=\"headerlink\" title=\"改变访问控制\"></a>改变访问控制</h1><h1 id=\"类型兼容性\"><a href=\"#类型兼容性\" class=\"headerlink\" title=\"类型兼容性\"></a>类型兼容性</h1><h1 id=\"类的类型转换\"><a href=\"#类的类型转换\" class=\"headerlink\" title=\"类的类型转换\"></a>类的类型转换</h1><h1 id=\"多重继承\"><a href=\"#多重继承\" class=\"headerlink\" title=\"多重继承\"></a>多重继承</h1>"},{"title":"运算符重载","top_img":"transparent","comments":0,"_content":"\n# 运算符重载\n\n<font color=red>**运算符重载的主要目的是:让运算符适用于自定义类型(类或结构体)**</font>\n\n## 运算符重载概念\n\n运算符重载是**具有特殊函数名的函数**,也具有返回值类型,函数名和参数列表\n重载的运算符可以理解为带有特殊名称的函数,函数名是由关键字 operator 和其后要重载的运算符符号构成的。\n\n### 重载的两种方法\n\n1.类成员函数运算符重载(类内定义)\n`return_type class_name::operator op(operand2) {}`\n重载二元运算符时,成员运算符函数只需显式传递一个参数(即二元运算符的右操作数),而左操作数则是该类对象本身,通过`this`指针隐式传递。\n\n重载一元运算符时,成员运算符函数没有参数,操作数是该类对象本身,通过`this`指针隐式传递\n\n2.友元函数运算符重载(类外定义)\n`return_type operator op(operand1, operand2) {}`\n\n<font color=red>**运算符重载至少需要一个操作数是用户定义的类型**</font>\n\n```cpp\nMyClass operator+(MyClass a, int b); // 合法(MyClass 是用户定义类型)\nint operator+(int a, int b); // 非法(两个操作数都是内置类型)\n```\n\n<font color=red>**运算符重载函数 可以返回基本数据类型**</font>\n\n### 不可以重载的运算符\n\n`::`(作用域解析)\n`.`(成员访问)\n`.*`(通过成员指针的成员访问)\n`?:`(三元条件)\n`sizeof`:运算符(包括除 new,delete 外的关\n键字运算符,如 alignof,typeid 等等)\n\n**其他限制:**\n• **不能创建新运算符**,例如 \\*\\*、<> 或 &|。\n\n• 运算符 && 与 || 的重载**失去短路求值**。\n\n• 重载的运算符 -> 必须要么返回裸指针,要么(按引用或值)返回同样重载了运算符 -> 的对象。\n\n• 不可能更改运算符的**优先级、结合方向或操作数的数量**。\n\n## 普通运算符重载\n\n双目,单目运算符重载\n例:\n\n| 运算符名 | 类内定义 | 类外定义 |\n| -------- | --------------------------------- | ----------------------------------- |\n| 一元加 | T T::operator+() const; | T operator+(const T& b); |\n| 加法 | T T::operator+(const T& b) const; | T operator+(const T& b,const T& c); |\n\n部分情况下,需要返回左值对象,可使用 T& 作为返回值。例如 operator<< 和 operator>> 作为流插入和流提取的重载所返回的是 T&\n\n## 自增/自减运算符重载\n\n若为前缀自增运算符,直接重载(以++举例):\n`• return_type class_name::operator ++() {}`\n\n```cpp\nInteger& operator ++ () {\ncerr<<\"prefix is invoked\"<<endl;\n++x;\nreturn *this;\n}\n```\n\n• 若为后缀自增运算符,该函数有一个 int 类型的虚拟形参,这个形参在函数的主体中是不会被使用的,这只是一个约定,它告诉编译器递增运算符正在后缀模式下被重载:\n`• return_type class_name::operator ++(int) {}`\n<font color=red>这也是前缀和后缀的主要区分</font>\n\n```cpp\nInteger operator ++ (int){\ncerr<<\"suffix is invoked\"<<endl;\nreturn Integer(x++);\n}\n```\n\n**要点:**\n\n1. 内建前缀运算符与后缀运算符原型不一样\n2. 前缀运算符,先增后用,一般返回增后的对象的引用(左值)\n3. 后缀运算符,先用后增,先建立原始对象的副本再自增,一般返回副本对象(右值)\n\n## 赋值运算符重载\n\n| 运算符名 | 语法 | 类内定义 | 类外定义 |\n| -------- | ---- | ------------------------------- | ------------------------------------ |\n| 简单赋值 | a=b | T& T::operator =(const T2& b); | N/A |\n| 加法赋值 | a+=b | T& T::operator +=(const T2& b); | T& operator +=(T& a ,const T2& b); |\n\n注意\n\n·所有内建赋值运算符都返回`*this`,而大多数用户定义重载也会返回`*this`,从而能以与内建版本相同的方式使用用户定义运算符。然而,用户定义运算符重载中,返回类型可以是<font color=red>任意类型</font>包括`void`。\n\n## 类型转换符重载\n\n基本语法\n\n```cpp\noperator type() const {\n // 转换逻辑\n return value;\n}\n```\n\n其中:\n1.type 是要转换的目标类型 2.必须是成员函数 3.不能指定返回类型(因为返回类型就是 type) 4.通常应该是 const 的,因为它不应该修改对象的状态\n\n```cpp\nclass MyInt {\n int value;\npublic:\n MyInt(int v) : value(v) {}\n // 转换为int的类型转换运算符\n operator int() const {\n return value;\n }\n // 转换为double的类型转换运算符\n operator double() const {\n return static_cast<double>(value);\n }\n};\n\nint main() {\n MyInt mi(42);\n int i = mi; // 隐式调用operator int()\n double d = mi; // 隐式调用operator double()\n // 显式转换\n int j = static_cast<int>(mi);\n}\n```\n\n## 浅复制与深复制策略\n\n**浅拷贝赋值**\n• 由缺省的赋值运算符完成,会按成员声明顺序逐一调用成员的赋值运算\n• 当成员是指针时,被赋值对象与赋值对象共用一个资源\n\n**深拷贝赋值**\n• 由用户定义的的赋值运算符完成。该函数不需要逐一调用非指针成员的赋\n值运算(但建议按声明顺序逐一赋值)\n• 当成员是指针时,需要释放已拥有资源,复制赋值对象对应的资源,并指\n向该资源的副本,即被赋值对象拥有赋值对象资源的副本\n\n**深拷贝策略**\n\n```cpp\nclass IntArray {\nint *a;\nint n;\npublic:\nIntArray(int n=1):n(n) {\na=new int[n];\nfor (int i=0;i<n;++i) a[i]=i;\n}\n~IntArray() {\ncout << \"release p=\" << a <<endl;\ndelete[] a;\n}\nIntArray& operator = (const IntArray& other) {\nif (this != &other) {\ndelete[] a; //这里a一定不为空\n n=other.n;\na=new int[n];\nmemcpy(a,other.a,sizeof(int)*n);\n}\nreturn *this;\n}\nvoid print() {\nfor (int i=0;i<n;++i) cout<<a[i]<<\" \";\ncout<<endl;\n}\n\nint main() {\nIntArray a(4), b;\na.print();\nb=a; // 调用深拷贝策略赋值\n b.print();\na.print(); //a,b point to ...\nreturn 0;\n}\n};\n```\n\n## 下标运算符重载\n\n**成员访问运算符**\nC++规定,下标运算符[]必须以成员函数的形式进行重载。该重载函数在类中的声明格式如下:\n\n```cpp\nR& T::operator[](S b); (1)\nconst R& T::operator[](S b) const; (2)\n```\n\n(1)声明方式,[]不仅可以访问元素,还可以修改元素。\n(2)声明方式,[]只能访问而不能修改元素。\n\n**在实际开发中,我们应该同时提供以上两种形式,这样做是为了适应 const 对象,因为通过 const 对象只能调用 const 成员函数,如果不提供第二种形式,那么将无法问 const 对象的任何元素。**\n\n例:\n\n```cpp\nclass IntArray {\nint *a;\nint n;\npublic:\nIntArray(int n=1):n(n) {…}\nIntArray(const IntArray& other) {…}\n~IntArray() {…}\nint& operator[](int i) {\nif (i>=0 && i < n) {\nreturn a[i];\n}\nthrow std::out_of_range(\"out of range\");\n}\nconst int& operator[](int i) const{\nif (i>=0 && i < n) {\nreturn a[i];\n}\nthrow std::out_of_range(\"out of range\");\n}\nvoid print() const {…\n}\n};\nint main() {\nIntArray a(4);\nfor (int i=0;i<4;i++) a[i]=i+1;\na.print();\n//任务1:以下两个语句,b的哪些成员函数被调用\n const IntArray b=a;\ncout << \"b[0] = \" << b[0] <<endl;\n//任务2:print函数去除 const会如何?\n b.print();\n//任务3:以下语句错误性质一样吗?\n //b[5]=10;\n//a[5]=10;\nreturn 0;\n}\n```\n\n## 函数对象\n\n### 函数调用\n\n函数对象:函数调用 运算符为任何对象提供函数语义。\n当一个类 T 定义了函数调用,则 T 类型的对象 a 就可以类似函数一样使用 a(…)。 T 也称为函数(callable)类。\n函数对象**既有对象持有状态的特征,又有函数可调用特征。**\n\n### 无状态\n\n当定义的 operator ()函数 没有使用对象的成员时,函数对象调用函数,其表现如同普通函数调用\n\n```cpp\nclass cmp {\npublic:\nbool operator () (const int& a, const int& b)\n{\nreturn a<b;\n}\n};\nint main() {\ncmp f;\ncout<<f(1,2)<<endl;\ncout<<f(2,1)<<endl;\nreturn 0;\n}\n```\n\n### 有状态\n\n当定义的 operator ()函数使用对象的成员时,函数对象调用函数,其形式如同普通函数调用一般,但其语义变为依赖对象本身内部状态。**同样的函数调用,结果却不同。**\n\n```cpp\nclass GreaterThan {\nint baseline;\npublic:\nGreaterThan(int x):baseline(x) { }\nbool operator () (const int& x) {\nreturn x>baseline;\n}\n};\nint main() {\nGreaterThan g1(10), g2(20);\ncout << g1(15) << endl;\ncout << g2(15) << endl;\nreturn 0;\n}\n```\n\n## 类外定义运算符重载\n\n例:\n\n```cpp\nstruct Integer {\nint x;\npublic:\nInteger(int x=0):x(x) {}\nInteger operator- (const Integer& Int) {\nreturn Integer(x-Int.x);\n}\nInteger operator - () {\nreturn Integer(-x);\n}\nvoid print() {\ncout<<x<<endl;\n}\n};\nInteger operator+(const Integer& lhs,const Integer&\nrhs) {\nreturn Integer(lhs.x+rhs.x);\n}\nint main() {\nInteger a=3,b,c;\n//任务1:解释两个赋值语句,哪些函数被调用\n b = a + 4;\nc = 5 + a;\nb.print();\nc.print();\n//任务2:将 struct 关键字改为 class\nreturn 0;\n}\n```\n\n## 友元与友元函数\n\n### friend 关键字\n\n顾名思义,友元函数就是给“朋友”看的函数,类内部声明 friend 普通函数,函数虽然不属于类,但却可以访问类的变量及函数(**包括私有的**)。**函数需要在类外实现**\n\n```\n友元函数(friend function)。\n• friend return_type function_name(parameter_type_list);\n```\n\n### 其他类成员函数作为友元\n\n类的成员函数也是函数的一种,所以其他类的成员函数也可以是友元函数!\n\n一个类 A 可以将另一个类 B 声明为自己的友元,那么类 B 的所有成员函数就都可以访问类 A 对象的私有成员\n`• friend class B; (在类 A 的内部)`\n\n## 操作符重载必须是成员函数的\n\n```cpp\na=b\na(b...)\na[b]\na->\n```\n\n## 重载匹配与隐式转换\n\n### 对象隐式转换\n\n**如果对象 T 存在构造函数 T(T1),则 T1 类型对象(实参)可隐式转为 T 类型对象(形参)**\n\n```cpp\nclass Integer {\nint x;\npublic:\nInteger(int x=0):x(x) {}\nfriend Integer operator+(const Integer &lhs,const Integer &rhs){\nreturn lhs.x + rhs.x;\n}\nfriend ostream& operator<<(ostream& o, const Integer &hs) {\no << hs.x;\nreturn o;\n}\nint main() {\nstring s;\ns = \"Hello\";\ncout << s << endl;\nInteger i1(3), i2;\ni2 = 1.1 + i1;\ncout << i2 << endl;\n}\n};\n```\n\n### 隐式转换-重载协议-const\n\n如果重载的函数参数一样,可以通过转换到某个重载函数,编译会如何哪个版本的选择?\n(1)类型直接匹配的优先选择;\n(2)const 类型实参匹配 const 版本\n(3)非 const 实参优先匹配非 const 版本。\n没有则隐式转换为 const 版本匹配\n\n```cpp\n/* 隐式转换-重载协议-const */\n…\nclass Integer {\nint x;\npublic:\nInteger(int x=0):x(x) {}\nfriend ostream& operator<<(ostream& o, const Integer &hs) {\no << \"const \" << hs.x;\nreturn o;\n}\nfriend ostream& operator<<(ostream& o, Integer &hs) {\no << \"no_const \" << hs.x ;\nreturn o;\n}\n};\nint main() {\nInteger i1(1);\nconst Integer i2(2);\ncout << i1 << \",\" << 3 << \",\" << i2 << endl;\n}\n```\n\n### explicit\n\nC++ 关键字 explicit,用于关闭这种自动类型转化的特性。\n\n即被 explicit 关键字修饰的类构造函数,不能进行自动地隐式类型转换,只能显式地进行类型转换\n\n### 隐式转换-nullptr\n\nC++ 引入了 nullptr 表示空值指针字面量。\n","source":"_posts/siventh-bolg.md","raw":"---\ntitle: 运算符重载\ntags: C++\ntop_img: transparent\ncomments: false\n---\n\n# 运算符重载\n\n<font color=red>**运算符重载的主要目的是:让运算符适用于自定义类型(类或结构体)**</font>\n\n## 运算符重载概念\n\n运算符重载是**具有特殊函数名的函数**,也具有返回值类型,函数名和参数列表\n重载的运算符可以理解为带有特殊名称的函数,函数名是由关键字 operator 和其后要重载的运算符符号构成的。\n\n### 重载的两种方法\n\n1.类成员函数运算符重载(类内定义)\n`return_type class_name::operator op(operand2) {}`\n重载二元运算符时,成员运算符函数只需显式传递一个参数(即二元运算符的右操作数),而左操作数则是该类对象本身,通过`this`指针隐式传递。\n\n重载一元运算符时,成员运算符函数没有参数,操作数是该类对象本身,通过`this`指针隐式传递\n\n2.友元函数运算符重载(类外定义)\n`return_type operator op(operand1, operand2) {}`\n\n<font color=red>**运算符重载至少需要一个操作数是用户定义的类型**</font>\n\n```cpp\nMyClass operator+(MyClass a, int b); // 合法(MyClass 是用户定义类型)\nint operator+(int a, int b); // 非法(两个操作数都是内置类型)\n```\n\n<font color=red>**运算符重载函数 可以返回基本数据类型**</font>\n\n### 不可以重载的运算符\n\n`::`(作用域解析)\n`.`(成员访问)\n`.*`(通过成员指针的成员访问)\n`?:`(三元条件)\n`sizeof`:运算符(包括除 new,delete 外的关\n键字运算符,如 alignof,typeid 等等)\n\n**其他限制:**\n• **不能创建新运算符**,例如 \\*\\*、<> 或 &|。\n\n• 运算符 && 与 || 的重载**失去短路求值**。\n\n• 重载的运算符 -> 必须要么返回裸指针,要么(按引用或值)返回同样重载了运算符 -> 的对象。\n\n• 不可能更改运算符的**优先级、结合方向或操作数的数量**。\n\n## 普通运算符重载\n\n双目,单目运算符重载\n例:\n\n| 运算符名 | 类内定义 | 类外定义 |\n| -------- | --------------------------------- | ----------------------------------- |\n| 一元加 | T T::operator+() const; | T operator+(const T& b); |\n| 加法 | T T::operator+(const T& b) const; | T operator+(const T& b,const T& c); |\n\n部分情况下,需要返回左值对象,可使用 T& 作为返回值。例如 operator<< 和 operator>> 作为流插入和流提取的重载所返回的是 T&\n\n## 自增/自减运算符重载\n\n若为前缀自增运算符,直接重载(以++举例):\n`• return_type class_name::operator ++() {}`\n\n```cpp\nInteger& operator ++ () {\ncerr<<\"prefix is invoked\"<<endl;\n++x;\nreturn *this;\n}\n```\n\n• 若为后缀自增运算符,该函数有一个 int 类型的虚拟形参,这个形参在函数的主体中是不会被使用的,这只是一个约定,它告诉编译器递增运算符正在后缀模式下被重载:\n`• return_type class_name::operator ++(int) {}`\n<font color=red>这也是前缀和后缀的主要区分</font>\n\n```cpp\nInteger operator ++ (int){\ncerr<<\"suffix is invoked\"<<endl;\nreturn Integer(x++);\n}\n```\n\n**要点:**\n\n1. 内建前缀运算符与后缀运算符原型不一样\n2. 前缀运算符,先增后用,一般返回增后的对象的引用(左值)\n3. 后缀运算符,先用后增,先建立原始对象的副本再自增,一般返回副本对象(右值)\n\n## 赋值运算符重载\n\n| 运算符名 | 语法 | 类内定义 | 类外定义 |\n| -------- | ---- | ------------------------------- | ------------------------------------ |\n| 简单赋值 | a=b | T& T::operator =(const T2& b); | N/A |\n| 加法赋值 | a+=b | T& T::operator +=(const T2& b); | T& operator +=(T& a ,const T2& b); |\n\n注意\n\n·所有内建赋值运算符都返回`*this`,而大多数用户定义重载也会返回`*this`,从而能以与内建版本相同的方式使用用户定义运算符。然而,用户定义运算符重载中,返回类型可以是<font color=red>任意类型</font>包括`void`。\n\n## 类型转换符重载\n\n基本语法\n\n```cpp\noperator type() const {\n // 转换逻辑\n return value;\n}\n```\n\n其中:\n1.type 是要转换的目标类型 2.必须是成员函数 3.不能指定返回类型(因为返回类型就是 type) 4.通常应该是 const 的,因为它不应该修改对象的状态\n\n```cpp\nclass MyInt {\n int value;\npublic:\n MyInt(int v) : value(v) {}\n // 转换为int的类型转换运算符\n operator int() const {\n return value;\n }\n // 转换为double的类型转换运算符\n operator double() const {\n return static_cast<double>(value);\n }\n};\n\nint main() {\n MyInt mi(42);\n int i = mi; // 隐式调用operator int()\n double d = mi; // 隐式调用operator double()\n // 显式转换\n int j = static_cast<int>(mi);\n}\n```\n\n## 浅复制与深复制策略\n\n**浅拷贝赋值**\n• 由缺省的赋值运算符完成,会按成员声明顺序逐一调用成员的赋值运算\n• 当成员是指针时,被赋值对象与赋值对象共用一个资源\n\n**深拷贝赋值**\n• 由用户定义的的赋值运算符完成。该函数不需要逐一调用非指针成员的赋\n值运算(但建议按声明顺序逐一赋值)\n• 当成员是指针时,需要释放已拥有资源,复制赋值对象对应的资源,并指\n向该资源的副本,即被赋值对象拥有赋值对象资源的副本\n\n**深拷贝策略**\n\n```cpp\nclass IntArray {\nint *a;\nint n;\npublic:\nIntArray(int n=1):n(n) {\na=new int[n];\nfor (int i=0;i<n;++i) a[i]=i;\n}\n~IntArray() {\ncout << \"release p=\" << a <<endl;\ndelete[] a;\n}\nIntArray& operator = (const IntArray& other) {\nif (this != &other) {\ndelete[] a; //这里a一定不为空\n n=other.n;\na=new int[n];\nmemcpy(a,other.a,sizeof(int)*n);\n}\nreturn *this;\n}\nvoid print() {\nfor (int i=0;i<n;++i) cout<<a[i]<<\" \";\ncout<<endl;\n}\n\nint main() {\nIntArray a(4), b;\na.print();\nb=a; // 调用深拷贝策略赋值\n b.print();\na.print(); //a,b point to ...\nreturn 0;\n}\n};\n```\n\n## 下标运算符重载\n\n**成员访问运算符**\nC++规定,下标运算符[]必须以成员函数的形式进行重载。该重载函数在类中的声明格式如下:\n\n```cpp\nR& T::operator[](S b); (1)\nconst R& T::operator[](S b) const; (2)\n```\n\n(1)声明方式,[]不仅可以访问元素,还可以修改元素。\n(2)声明方式,[]只能访问而不能修改元素。\n\n**在实际开发中,我们应该同时提供以上两种形式,这样做是为了适应 const 对象,因为通过 const 对象只能调用 const 成员函数,如果不提供第二种形式,那么将无法问 const 对象的任何元素。**\n\n例:\n\n```cpp\nclass IntArray {\nint *a;\nint n;\npublic:\nIntArray(int n=1):n(n) {…}\nIntArray(const IntArray& other) {…}\n~IntArray() {…}\nint& operator[](int i) {\nif (i>=0 && i < n) {\nreturn a[i];\n}\nthrow std::out_of_range(\"out of range\");\n}\nconst int& operator[](int i) const{\nif (i>=0 && i < n) {\nreturn a[i];\n}\nthrow std::out_of_range(\"out of range\");\n}\nvoid print() const {…\n}\n};\nint main() {\nIntArray a(4);\nfor (int i=0;i<4;i++) a[i]=i+1;\na.print();\n//任务1:以下两个语句,b的哪些成员函数被调用\n const IntArray b=a;\ncout << \"b[0] = \" << b[0] <<endl;\n//任务2:print函数去除 const会如何?\n b.print();\n//任务3:以下语句错误性质一样吗?\n //b[5]=10;\n//a[5]=10;\nreturn 0;\n}\n```\n\n## 函数对象\n\n### 函数调用\n\n函数对象:函数调用 运算符为任何对象提供函数语义。\n当一个类 T 定义了函数调用,则 T 类型的对象 a 就可以类似函数一样使用 a(…)。 T 也称为函数(callable)类。\n函数对象**既有对象持有状态的特征,又有函数可调用特征。**\n\n### 无状态\n\n当定义的 operator ()函数 没有使用对象的成员时,函数对象调用函数,其表现如同普通函数调用\n\n```cpp\nclass cmp {\npublic:\nbool operator () (const int& a, const int& b)\n{\nreturn a<b;\n}\n};\nint main() {\ncmp f;\ncout<<f(1,2)<<endl;\ncout<<f(2,1)<<endl;\nreturn 0;\n}\n```\n\n### 有状态\n\n当定义的 operator ()函数使用对象的成员时,函数对象调用函数,其形式如同普通函数调用一般,但其语义变为依赖对象本身内部状态。**同样的函数调用,结果却不同。**\n\n```cpp\nclass GreaterThan {\nint baseline;\npublic:\nGreaterThan(int x):baseline(x) { }\nbool operator () (const int& x) {\nreturn x>baseline;\n}\n};\nint main() {\nGreaterThan g1(10), g2(20);\ncout << g1(15) << endl;\ncout << g2(15) << endl;\nreturn 0;\n}\n```\n\n## 类外定义运算符重载\n\n例:\n\n```cpp\nstruct Integer {\nint x;\npublic:\nInteger(int x=0):x(x) {}\nInteger operator- (const Integer& Int) {\nreturn Integer(x-Int.x);\n}\nInteger operator - () {\nreturn Integer(-x);\n}\nvoid print() {\ncout<<x<<endl;\n}\n};\nInteger operator+(const Integer& lhs,const Integer&\nrhs) {\nreturn Integer(lhs.x+rhs.x);\n}\nint main() {\nInteger a=3,b,c;\n//任务1:解释两个赋值语句,哪些函数被调用\n b = a + 4;\nc = 5 + a;\nb.print();\nc.print();\n//任务2:将 struct 关键字改为 class\nreturn 0;\n}\n```\n\n## 友元与友元函数\n\n### friend 关键字\n\n顾名思义,友元函数就是给“朋友”看的函数,类内部声明 friend 普通函数,函数虽然不属于类,但却可以访问类的变量及函数(**包括私有的**)。**函数需要在类外实现**\n\n```\n友元函数(friend function)。\n• friend return_type function_name(parameter_type_list);\n```\n\n### 其他类成员函数作为友元\n\n类的成员函数也是函数的一种,所以其他类的成员函数也可以是友元函数!\n\n一个类 A 可以将另一个类 B 声明为自己的友元,那么类 B 的所有成员函数就都可以访问类 A 对象的私有成员\n`• friend class B; (在类 A 的内部)`\n\n## 操作符重载必须是成员函数的\n\n```cpp\na=b\na(b...)\na[b]\na->\n```\n\n## 重载匹配与隐式转换\n\n### 对象隐式转换\n\n**如果对象 T 存在构造函数 T(T1),则 T1 类型对象(实参)可隐式转为 T 类型对象(形参)**\n\n```cpp\nclass Integer {\nint x;\npublic:\nInteger(int x=0):x(x) {}\nfriend Integer operator+(const Integer &lhs,const Integer &rhs){\nreturn lhs.x + rhs.x;\n}\nfriend ostream& operator<<(ostream& o, const Integer &hs) {\no << hs.x;\nreturn o;\n}\nint main() {\nstring s;\ns = \"Hello\";\ncout << s << endl;\nInteger i1(3), i2;\ni2 = 1.1 + i1;\ncout << i2 << endl;\n}\n};\n```\n\n### 隐式转换-重载协议-const\n\n如果重载的函数参数一样,可以通过转换到某个重载函数,编译会如何哪个版本的选择?\n(1)类型直接匹配的优先选择;\n(2)const 类型实参匹配 const 版本\n(3)非 const 实参优先匹配非 const 版本。\n没有则隐式转换为 const 版本匹配\n\n```cpp\n/* 隐式转换-重载协议-const */\n…\nclass Integer {\nint x;\npublic:\nInteger(int x=0):x(x) {}\nfriend ostream& operator<<(ostream& o, const Integer &hs) {\no << \"const \" << hs.x;\nreturn o;\n}\nfriend ostream& operator<<(ostream& o, Integer &hs) {\no << \"no_const \" << hs.x ;\nreturn o;\n}\n};\nint main() {\nInteger i1(1);\nconst Integer i2(2);\ncout << i1 << \",\" << 3 << \",\" << i2 << endl;\n}\n```\n\n### explicit\n\nC++ 关键字 explicit,用于关闭这种自动类型转化的特性。\n\n即被 explicit 关键字修饰的类构造函数,不能进行自动地隐式类型转换,只能显式地进行类型转换\n\n### 隐式转换-nullptr\n\nC++ 引入了 nullptr 表示空值指针字面量。\n","slug":"siventh-bolg","published":1,"date":"2025-04-10T06:45:10.381Z","updated":"2025-04-27T11:49:12.989Z","layout":"post","photos":[],"_id":"cmkmd8tyy000icw647u5m6r00","content":"<link rel=\"stylesheet\" class=\"aplayer-secondary-style-marker\" href=\"\\assets\\css\\APlayer.min.css\"><script src=\"\\assets\\js\\APlayer.min.js\" class=\"aplayer-secondary-script-marker\"></script><h1 id=\"运算符重载\"><a href=\"#运算符重载\" class=\"headerlink\" title=\"运算符重载\"></a>运算符重载</h1><p><font color=red><strong>运算符重载的主要目的是:让运算符适用于自定义类型(类或结构体)</strong></font></p>\n<h2 id=\"运算符重载概念\"><a href=\"#运算符重载概念\" class=\"headerlink\" title=\"运算符重载概念\"></a>运算符重载概念</h2><p>运算符重载是<strong>具有特殊函数名的函数</strong>,也具有返回值类型,函数名和参数列表<br>重载的运算符可以理解为带有特殊名称的函数,函数名是由关键字 operator 和其后要重载的运算符符号构成的。</p>\n<h3 id=\"重载的两种方法\"><a href=\"#重载的两种方法\" class=\"headerlink\" title=\"重载的两种方法\"></a>重载的两种方法</h3><p>1.类成员函数运算符重载(类内定义)<br><code>return_type class_name::operator op(operand2) {}</code><br>重载二元运算符时,成员运算符函数只需显式传递一个参数(即二元运算符的右操作数),而左操作数则是该类对象本身,通过<code>this</code>指针隐式传递。</p>\n<p>重载一元运算符时,成员运算符函数没有参数,操作数是该类对象本身,通过<code>this</code>指针隐式传递</p>\n<p>2.友元函数运算符重载(类外定义)<br><code>return_type operator op(operand1, operand2) {}</code></p>\n<p><font color=red><strong>运算符重载至少需要一个操作数是用户定义的类型</strong></font></p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\">MyClass <span class=\"keyword\">operator</span>+(MyClass a, <span class=\"type\">int</span> b); <span class=\"comment\">// 合法(MyClass 是用户定义类型)</span></span><br><span class=\"line\"><span class=\"type\">int</span> <span class=\"keyword\">operator</span>+(<span class=\"type\">int</span> a, <span class=\"type\">int</span> b); <span class=\"comment\">// 非法(两个操作数都是内置类型)</span></span><br></pre></td></tr></table></figure>\n\n<p><font color=red><strong>运算符重载函数 可以返回基本数据类型</strong></font></p>\n<h3 id=\"不可以重载的运算符\"><a href=\"#不可以重载的运算符\" class=\"headerlink\" title=\"不可以重载的运算符\"></a>不可以重载的运算符</h3><p><code>::</code>(作用域解析)<br><code>.</code>(成员访问)<br><code>.*</code>(通过成员指针的成员访问)<br><code>?:</code>(三元条件)<br><code>sizeof</code>:运算符(包括除 new,delete 外的关<br>键字运算符,如 alignof,typeid 等等)</p>\n<p><strong>其他限制:</strong><br>• <strong>不能创建新运算符</strong>,例如 **、<> 或 &|。</p>\n<p>• 运算符 && 与 || 的重载<strong>失去短路求值</strong>。</p>\n<p>• 重载的运算符 -> 必须要么返回裸指针,要么(按引用或值)返回同样重载了运算符 -> 的对象。</p>\n<p>• 不可能更改运算符的<strong>优先级、结合方向或操作数的数量</strong>。</p>\n<h2 id=\"普通运算符重载\"><a href=\"#普通运算符重载\" class=\"headerlink\" title=\"普通运算符重载\"></a>普通运算符重载</h2><p>双目,单目运算符重载<br>例:</p>\n<table>\n<thead>\n<tr>\n<th>运算符名</th>\n<th>类内定义</th>\n<th>类外定义</th>\n</tr>\n</thead>\n<tbody><tr>\n<td>一元加</td>\n<td>T T::operator+() const;</td>\n<td>T operator+(const T& b);</td>\n</tr>\n<tr>\n<td>加法</td>\n<td>T T::operator+(const T& b) const;</td>\n<td>T operator+(const T& b,const T& c);</td>\n</tr>\n</tbody></table>\n<p>部分情况下,需要返回左值对象,可使用 T& 作为返回值。例如 operator<< 和 operator>> 作为流插入和流提取的重载所返回的是 T&</p>\n<h2 id=\"自增-自减运算符重载\"><a href=\"#自增-自减运算符重载\" class=\"headerlink\" title=\"自增/自减运算符重载\"></a>自增/自减运算符重载</h2><p>若为前缀自增运算符,直接重载(以++举例):<br><code>• return_type class_name::operator ++() {}</code></p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\">Integer& <span class=\"keyword\">operator</span> ++ () {</span><br><span class=\"line\">cerr<<<span class=\"string\">"prefix is invoked"</span><<endl;</span><br><span class=\"line\">++x;</span><br><span class=\"line\"><span class=\"keyword\">return</span> *<span class=\"keyword\">this</span>;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<p>• 若为后缀自增运算符,该函数有一个 int 类型的虚拟形参,这个形参在函数的主体中是不会被使用的,这只是一个约定,它告诉编译器递增运算符正在后缀模式下被重载:<br><code>• return_type class_name::operator ++(int) {}</code><br><font color=red>这也是前缀和后缀的主要区分</font></p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\">Integer <span class=\"keyword\">operator</span> ++ (<span class=\"type\">int</span>){</span><br><span class=\"line\">cerr<<<span class=\"string\">"suffix is invoked"</span><<endl;</span><br><span class=\"line\"><span class=\"keyword\">return</span> <span class=\"built_in\">Integer</span>(x++);</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<p><strong>要点:</strong></p>\n<ol>\n<li>内建前缀运算符与后缀运算符原型不一样</li>\n<li>前缀运算符,先增后用,一般返回增后的对象的引用(左值)</li>\n<li>后缀运算符,先用后增,先建立原始对象的副本再自增,一般返回副本对象(右值)</li>\n</ol>\n<h2 id=\"赋值运算符重载\"><a href=\"#赋值运算符重载\" class=\"headerlink\" title=\"赋值运算符重载\"></a>赋值运算符重载</h2><table>\n<thead>\n<tr>\n<th>运算符名</th>\n<th>语法</th>\n<th>类内定义</th>\n<th>类外定义</th>\n</tr>\n</thead>\n<tbody><tr>\n<td>简单赋值</td>\n<td>a=b</td>\n<td>T& T::operator =(const T2& b);</td>\n<td>N/A</td>\n</tr>\n<tr>\n<td>加法赋值</td>\n<td>a+=b</td>\n<td>T& T::operator +=(const T2& b);</td>\n<td>T& operator +=(T& a ,const T2& b);</td>\n</tr>\n</tbody></table>\n<p>注意</p>\n<p>·所有内建赋值运算符都返回<code>*this</code>,而大多数用户定义重载也会返回<code>*this</code>,从而能以与内建版本相同的方式使用用户定义运算符。然而,用户定义运算符重载中,返回类型可以是<font color=red>任意类型</font>包括<code>void</code>。</p>\n<h2 id=\"类型转换符重载\"><a href=\"#类型转换符重载\" class=\"headerlink\" title=\"类型转换符重载\"></a>类型转换符重载</h2><p>基本语法</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"function\"><span class=\"keyword\">operator</span> <span class=\"title\">type</span><span class=\"params\">()</span> <span class=\"type\">const</span> </span>{</span><br><span class=\"line\"> <span class=\"comment\">// 转换逻辑</span></span><br><span class=\"line\"> <span class=\"keyword\">return</span> value;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<p>其中:<br>1.type 是要转换的目标类型 2.必须是成员函数 3.不能指定返回类型(因为返回类型就是 type) 4.通常应该是 const 的,因为它不应该修改对象的状态</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">class</span> <span class=\"title class_\">MyInt</span> {</span><br><span class=\"line\"> <span class=\"type\">int</span> value;</span><br><span class=\"line\"><span class=\"keyword\">public</span>:</span><br><span class=\"line\"> <span class=\"built_in\">MyInt</span>(<span class=\"type\">int</span> v) : <span class=\"built_in\">value</span>(v) {}</span><br><span class=\"line\"> <span class=\"comment\">// 转换为int的类型转换运算符</span></span><br><span class=\"line\"> <span class=\"function\"><span class=\"keyword\">operator</span> <span class=\"title\">int</span><span class=\"params\">()</span> <span class=\"type\">const</span> </span>{</span><br><span class=\"line\"> <span class=\"keyword\">return</span> value;</span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"comment\">// 转换为double的类型转换运算符</span></span><br><span class=\"line\"> <span class=\"function\"><span class=\"keyword\">operator</span> <span class=\"title\">double</span><span class=\"params\">()</span> <span class=\"type\">const</span> </span>{</span><br><span class=\"line\"> <span class=\"keyword\">return</span> <span class=\"built_in\">static_cast</span><<span class=\"type\">double</span>>(value);</span><br><span class=\"line\"> }</span><br><span class=\"line\">};</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span><span class=\"params\">()</span> </span>{</span><br><span class=\"line\"> <span class=\"function\">MyInt <span class=\"title\">mi</span><span class=\"params\">(<span class=\"number\">42</span>)</span></span>;</span><br><span class=\"line\"> <span class=\"type\">int</span> i = mi; <span class=\"comment\">// 隐式调用operator int()</span></span><br><span class=\"line\"> <span class=\"type\">double</span> d = mi; <span class=\"comment\">// 隐式调用operator double()</span></span><br><span class=\"line\"> <span class=\"comment\">// 显式转换</span></span><br><span class=\"line\"> <span class=\"type\">int</span> j = <span class=\"built_in\">static_cast</span><<span class=\"type\">int</span>>(mi);</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<h2 id=\"浅复制与深复制策略\"><a href=\"#浅复制与深复制策略\" class=\"headerlink\" title=\"浅复制与深复制策略\"></a>浅复制与深复制策略</h2><p><strong>浅拷贝赋值</strong><br>• 由缺省的赋值运算符完成,会按成员声明顺序逐一调用成员的赋值运算<br>• 当成员是指针时,被赋值对象与赋值对象共用一个资源</p>\n<p><strong>深拷贝赋值</strong><br>• 由用户定义的的赋值运算符完成。该函数不需要逐一调用非指针成员的赋<br>值运算(但建议按声明顺序逐一赋值)<br>• 当成员是指针时,需要释放已拥有资源,复制赋值对象对应的资源,并指<br>向该资源的副本,即被赋值对象拥有赋值对象资源的副本</p>\n<p><strong>深拷贝策略</strong></p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">class</span> <span class=\"title class_\">IntArray</span> {</span><br><span class=\"line\"><span class=\"type\">int</span> *a;</span><br><span class=\"line\"><span class=\"type\">int</span> n;</span><br><span class=\"line\"><span class=\"keyword\">public</span>:</span><br><span class=\"line\"><span class=\"built_in\">IntArray</span>(<span class=\"type\">int</span> n=<span class=\"number\">1</span>):<span class=\"built_in\">n</span>(n) {</span><br><span class=\"line\">a=<span class=\"keyword\">new</span> <span class=\"type\">int</span>[n];</span><br><span class=\"line\"><span class=\"keyword\">for</span> (<span class=\"type\">int</span> i=<span class=\"number\">0</span>;i<n;++i) a[i]=i;</span><br><span class=\"line\">}</span><br><span class=\"line\">~<span class=\"built_in\">IntArray</span>() {</span><br><span class=\"line\">cout << <span class=\"string\">"release p="</span> << a <<endl;</span><br><span class=\"line\"><span class=\"keyword\">delete</span>[] a;</span><br><span class=\"line\">}</span><br><span class=\"line\">IntArray& <span class=\"keyword\">operator</span> = (<span class=\"type\">const</span> IntArray& other) {</span><br><span class=\"line\"><span class=\"keyword\">if</span> (<span class=\"keyword\">this</span> != &other) {</span><br><span class=\"line\"><span class=\"keyword\">delete</span>[] a; <span class=\"comment\">//这里a一定不为空</span></span><br><span class=\"line\"> n=other.n;</span><br><span class=\"line\">a=<span class=\"keyword\">new</span> <span class=\"type\">int</span>[n];</span><br><span class=\"line\"><span class=\"built_in\">memcpy</span>(a,other.a,<span class=\"built_in\">sizeof</span>(<span class=\"type\">int</span>)*n);</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"keyword\">return</span> *<span class=\"keyword\">this</span>;</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">void</span> <span class=\"title\">print</span><span class=\"params\">()</span> </span>{</span><br><span class=\"line\"><span class=\"keyword\">for</span> (<span class=\"type\">int</span> i=<span class=\"number\">0</span>;i<n;++i) cout<<a[i]<<<span class=\"string\">" "</span>;</span><br><span class=\"line\">cout<<endl;</span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span><span class=\"params\">()</span> </span>{</span><br><span class=\"line\"><span class=\"function\">IntArray <span class=\"title\">a</span><span class=\"params\">(<span class=\"number\">4</span>)</span>, b</span>;</span><br><span class=\"line\">a.<span class=\"built_in\">print</span>();</span><br><span class=\"line\">b=a; <span class=\"comment\">// 调用深拷贝策略赋值</span></span><br><span class=\"line\"> b.<span class=\"built_in\">print</span>();</span><br><span class=\"line\">a.<span class=\"built_in\">print</span>(); <span class=\"comment\">//a,b point to ...</span></span><br><span class=\"line\"><span class=\"keyword\">return</span> <span class=\"number\">0</span>;</span><br><span class=\"line\">}</span><br><span class=\"line\">};</span><br></pre></td></tr></table></figure>\n\n<h2 id=\"下标运算符重载\"><a href=\"#下标运算符重载\" class=\"headerlink\" title=\"下标运算符重载\"></a>下标运算符重载</h2><p><strong>成员访问运算符</strong><br>C++规定,下标运算符[]必须以成员函数的形式进行重载。该重载函数在类中的声明格式如下:</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\">R& T::<span class=\"keyword\">operator</span>[](S b); (<span class=\"number\">1</span>)</span><br><span class=\"line\"><span class=\"type\">const</span> R& T::<span class=\"keyword\">operator</span>[](S b) <span class=\"type\">const</span>; (<span class=\"number\">2</span>)</span><br></pre></td></tr></table></figure>\n\n<p>(1)声明方式,[]不仅可以访问元素,还可以修改元素。<br>(2)声明方式,[]只能访问而不能修改元素。</p>\n<p><strong>在实际开发中,我们应该同时提供以上两种形式,这样做是为了适应 const 对象,因为通过 const 对象只能调用 const 成员函数,如果不提供第二种形式,那么将无法问 const 对象的任何元素。</strong></p>\n<p>例:</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">class</span> <span class=\"title class_\">IntArray</span> {</span><br><span class=\"line\"><span class=\"type\">int</span> *a;</span><br><span class=\"line\"><span class=\"type\">int</span> n;</span><br><span class=\"line\"><span class=\"keyword\">public</span>:</span><br><span class=\"line\"><span class=\"built_in\">IntArray</span>(<span class=\"type\">int</span> n=<span class=\"number\">1</span>):<span class=\"built_in\">n</span>(n) {…}</span><br><span class=\"line\"><span class=\"built_in\">IntArray</span>(<span class=\"type\">const</span> IntArray& other) {…}</span><br><span class=\"line\">~<span class=\"built_in\">IntArray</span>() {…}</span><br><span class=\"line\"><span class=\"type\">int</span>& <span class=\"keyword\">operator</span>[](<span class=\"type\">int</span> i) {</span><br><span class=\"line\"><span class=\"keyword\">if</span> (i>=<span class=\"number\">0</span> && i < n) {</span><br><span class=\"line\"><span class=\"keyword\">return</span> a[i];</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"keyword\">throw</span> std::<span class=\"built_in\">out_of_range</span>(<span class=\"string\">"out of range"</span>);</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"type\">const</span> <span class=\"type\">int</span>& <span class=\"keyword\">operator</span>[](<span class=\"type\">int</span> i) <span class=\"type\">const</span>{</span><br><span class=\"line\"><span class=\"keyword\">if</span> (i>=<span class=\"number\">0</span> && i < n) {</span><br><span class=\"line\"><span class=\"keyword\">return</span> a[i];</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"keyword\">throw</span> std::<span class=\"built_in\">out_of_range</span>(<span class=\"string\">"out of range"</span>);</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">void</span> <span class=\"title\">print</span><span class=\"params\">()</span> <span class=\"type\">const</span> </span>{…</span><br><span class=\"line\">}</span><br><span class=\"line\">};</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span><span class=\"params\">()</span> </span>{</span><br><span class=\"line\"><span class=\"function\">IntArray <span class=\"title\">a</span><span class=\"params\">(<span class=\"number\">4</span>)</span></span>;</span><br><span class=\"line\"><span class=\"keyword\">for</span> (<span class=\"type\">int</span> i=<span class=\"number\">0</span>;i<<span class=\"number\">4</span>;i++) a[i]=i<span class=\"number\">+1</span>;</span><br><span class=\"line\">a.<span class=\"built_in\">print</span>();</span><br><span class=\"line\"><span class=\"comment\">//任务1:以下两个语句,b的哪些成员函数被调用</span></span><br><span class=\"line\"> <span class=\"type\">const</span> IntArray b=a;</span><br><span class=\"line\">cout << <span class=\"string\">"b[0] = "</span> << b[<span class=\"number\">0</span>] <<endl;</span><br><span class=\"line\"><span class=\"comment\">//任务2:print函数去除 const会如何?</span></span><br><span class=\"line\"> b.<span class=\"built_in\">print</span>();</span><br><span class=\"line\"><span class=\"comment\">//任务3:以下语句错误性质一样吗?</span></span><br><span class=\"line\"> <span class=\"comment\">//b[5]=10;</span></span><br><span class=\"line\"><span class=\"comment\">//a[5]=10;</span></span><br><span class=\"line\"><span class=\"keyword\">return</span> <span class=\"number\">0</span>;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<h2 id=\"函数对象\"><a href=\"#函数对象\" class=\"headerlink\" title=\"函数对象\"></a>函数对象</h2><h3 id=\"函数调用\"><a href=\"#函数调用\" class=\"headerlink\" title=\"函数调用\"></a>函数调用</h3><p>函数对象:函数调用 运算符为任何对象提供函数语义。<br>当一个类 T 定义了函数调用,则 T 类型的对象 a 就可以类似函数一样使用 a(…)。 T 也称为函数(callable)类。<br>函数对象<strong>既有对象持有状态的特征,又有函数可调用特征。</strong></p>\n<h3 id=\"无状态\"><a href=\"#无状态\" class=\"headerlink\" title=\"无状态\"></a>无状态</h3><p>当定义的 operator ()函数 没有使用对象的成员时,函数对象调用函数,其表现如同普通函数调用</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">class</span> <span class=\"title class_\">cmp</span> {</span><br><span class=\"line\"><span class=\"keyword\">public</span>:</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">bool</span> <span class=\"title\">operator</span> <span class=\"params\">()</span> <span class=\"params\">(<span class=\"type\">const</span> <span class=\"type\">int</span>& a, <span class=\"type\">const</span> <span class=\"type\">int</span>& b)</span></span></span><br><span class=\"line\"><span class=\"function\"></span>{</span><br><span class=\"line\"><span class=\"keyword\">return</span> a<b;</span><br><span class=\"line\">}</span><br><span class=\"line\">};</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span><span class=\"params\">()</span> </span>{</span><br><span class=\"line\">cmp f;</span><br><span class=\"line\">cout<<<span class=\"built_in\">f</span>(<span class=\"number\">1</span>,<span class=\"number\">2</span>)<<endl;</span><br><span class=\"line\">cout<<<span class=\"built_in\">f</span>(<span class=\"number\">2</span>,<span class=\"number\">1</span>)<<endl;</span><br><span class=\"line\"><span class=\"keyword\">return</span> <span class=\"number\">0</span>;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<h3 id=\"有状态\"><a href=\"#有状态\" class=\"headerlink\" title=\"有状态\"></a>有状态</h3><p>当定义的 operator ()函数使用对象的成员时,函数对象调用函数,其形式如同普通函数调用一般,但其语义变为依赖对象本身内部状态。<strong>同样的函数调用,结果却不同。</strong></p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">class</span> <span class=\"title class_\">GreaterThan</span> {</span><br><span class=\"line\"><span class=\"type\">int</span> baseline;</span><br><span class=\"line\"><span class=\"keyword\">public</span>:</span><br><span class=\"line\"><span class=\"built_in\">GreaterThan</span>(<span class=\"type\">int</span> x):<span class=\"built_in\">baseline</span>(x) { }</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">bool</span> <span class=\"title\">operator</span> <span class=\"params\">()</span> <span class=\"params\">(<span class=\"type\">const</span> <span class=\"type\">int</span>& x)</span> </span>{</span><br><span class=\"line\"><span class=\"keyword\">return</span> x>baseline;</span><br><span class=\"line\">}</span><br><span class=\"line\">};</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span><span class=\"params\">()</span> </span>{</span><br><span class=\"line\"><span class=\"function\">GreaterThan <span class=\"title\">g1</span><span class=\"params\">(<span class=\"number\">10</span>)</span>, <span class=\"title\">g2</span><span class=\"params\">(<span class=\"number\">20</span>)</span></span>;</span><br><span class=\"line\">cout << <span class=\"built_in\">g1</span>(<span class=\"number\">15</span>) << endl;</span><br><span class=\"line\">cout << <span class=\"built_in\">g2</span>(<span class=\"number\">15</span>) << endl;</span><br><span class=\"line\"><span class=\"keyword\">return</span> <span class=\"number\">0</span>;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<h2 id=\"类外定义运算符重载\"><a href=\"#类外定义运算符重载\" class=\"headerlink\" title=\"类外定义运算符重载\"></a>类外定义运算符重载</h2><p>例:</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">struct</span> <span class=\"title class_\">Integer</span> {</span><br><span class=\"line\"><span class=\"type\">int</span> x;</span><br><span class=\"line\"><span class=\"keyword\">public</span>:</span><br><span class=\"line\"><span class=\"built_in\">Integer</span>(<span class=\"type\">int</span> x=<span class=\"number\">0</span>):<span class=\"built_in\">x</span>(x) {}</span><br><span class=\"line\">Integer <span class=\"keyword\">operator</span>- (<span class=\"type\">const</span> Integer& Int) {</span><br><span class=\"line\"><span class=\"keyword\">return</span> <span class=\"built_in\">Integer</span>(x-Int.x);</span><br><span class=\"line\">}</span><br><span class=\"line\">Integer <span class=\"keyword\">operator</span> - () {</span><br><span class=\"line\"><span class=\"keyword\">return</span> <span class=\"built_in\">Integer</span>(-x);</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">void</span> <span class=\"title\">print</span><span class=\"params\">()</span> </span>{</span><br><span class=\"line\">cout<<x<<endl;</span><br><span class=\"line\">}</span><br><span class=\"line\">};</span><br><span class=\"line\">Integer <span class=\"keyword\">operator</span>+(<span class=\"type\">const</span> Integer& lhs,<span class=\"type\">const</span> Integer&</span><br><span class=\"line\">rhs) {</span><br><span class=\"line\"><span class=\"keyword\">return</span> <span class=\"built_in\">Integer</span>(lhs.x+rhs.x);</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span><span class=\"params\">()</span> </span>{</span><br><span class=\"line\">Integer a=<span class=\"number\">3</span>,b,c;</span><br><span class=\"line\"><span class=\"comment\">//任务1:解释两个赋值语句,哪些函数被调用</span></span><br><span class=\"line\"> b = a + <span class=\"number\">4</span>;</span><br><span class=\"line\">c = <span class=\"number\">5</span> + a;</span><br><span class=\"line\">b.<span class=\"built_in\">print</span>();</span><br><span class=\"line\">c.<span class=\"built_in\">print</span>();</span><br><span class=\"line\"><span class=\"comment\">//任务2:将 struct 关键字改为 class</span></span><br><span class=\"line\"><span class=\"keyword\">return</span> <span class=\"number\">0</span>;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<h2 id=\"友元与友元函数\"><a href=\"#友元与友元函数\" class=\"headerlink\" title=\"友元与友元函数\"></a>友元与友元函数</h2><h3 id=\"friend-关键字\"><a href=\"#friend-关键字\" class=\"headerlink\" title=\"friend 关键字\"></a>friend 关键字</h3><p>顾名思义,友元函数就是给“朋友”看的函数,类内部声明 friend 普通函数,函数虽然不属于类,但却可以访问类的变量及函数(<strong>包括私有的</strong>)。<strong>函数需要在类外实现</strong></p>\n<figure class=\"highlight arduino\"><table><tr><td class=\"code\"><pre><span class=\"line\">友元函数(<span class=\"keyword\">friend</span> function)。</span><br><span class=\"line\">• <span class=\"function\"><span class=\"keyword\">friend</span> return_type <span class=\"title\">function_name</span><span class=\"params\">(parameter_type_list)</span></span>;</span><br></pre></td></tr></table></figure>\n\n<h3 id=\"其他类成员函数作为友元\"><a href=\"#其他类成员函数作为友元\" class=\"headerlink\" title=\"其他类成员函数作为友元\"></a>其他类成员函数作为友元</h3><p>类的成员函数也是函数的一种,所以其他类的成员函数也可以是友元函数!</p>\n<p>一个类 A 可以将另一个类 B 声明为自己的友元,那么类 B 的所有成员函数就都可以访问类 A 对象的私有成员<br><code>• friend class B; (在类 A 的内部)</code></p>\n<h2 id=\"操作符重载必须是成员函数的\"><a href=\"#操作符重载必须是成员函数的\" class=\"headerlink\" title=\"操作符重载必须是成员函数的\"></a>操作符重载必须是成员函数的</h2><figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\">a=b</span><br><span class=\"line\"><span class=\"built_in\">a</span>(b...)</span><br><span class=\"line\">a[b]</span><br><span class=\"line\">a-></span><br></pre></td></tr></table></figure>\n\n<h2 id=\"重载匹配与隐式转换\"><a href=\"#重载匹配与隐式转换\" class=\"headerlink\" title=\"重载匹配与隐式转换\"></a>重载匹配与隐式转换</h2><h3 id=\"对象隐式转换\"><a href=\"#对象隐式转换\" class=\"headerlink\" title=\"对象隐式转换\"></a>对象隐式转换</h3><p><strong>如果对象 T 存在构造函数 T(T1),则 T1 类型对象(实参)可隐式转为 T 类型对象(形参)</strong></p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">class</span> <span class=\"title class_\">Integer</span> {</span><br><span class=\"line\"><span class=\"type\">int</span> x;</span><br><span class=\"line\"><span class=\"keyword\">public</span>:</span><br><span class=\"line\"><span class=\"built_in\">Integer</span>(<span class=\"type\">int</span> x=<span class=\"number\">0</span>):<span class=\"built_in\">x</span>(x) {}</span><br><span class=\"line\"><span class=\"keyword\">friend</span> Integer <span class=\"keyword\">operator</span>+(<span class=\"type\">const</span> Integer &lhs,<span class=\"type\">const</span> Integer &rhs){</span><br><span class=\"line\"><span class=\"keyword\">return</span> lhs.x + rhs.x;</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"keyword\">friend</span> ostream& <span class=\"keyword\">operator</span><<(ostream& o, <span class=\"type\">const</span> Integer &hs) {</span><br><span class=\"line\">o << hs.x;</span><br><span class=\"line\"><span class=\"keyword\">return</span> o;</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span><span class=\"params\">()</span> </span>{</span><br><span class=\"line\">string s;</span><br><span class=\"line\">s = <span class=\"string\">"Hello"</span>;</span><br><span class=\"line\">cout << s << endl;</span><br><span class=\"line\"><span class=\"function\">Integer <span class=\"title\">i1</span><span class=\"params\">(<span class=\"number\">3</span>)</span>, i2</span>;</span><br><span class=\"line\">i2 = <span class=\"number\">1.1</span> + i1;</span><br><span class=\"line\">cout << i2 << endl;</span><br><span class=\"line\">}</span><br><span class=\"line\">};</span><br></pre></td></tr></table></figure>\n\n<h3 id=\"隐式转换-重载协议-const\"><a href=\"#隐式转换-重载协议-const\" class=\"headerlink\" title=\"隐式转换-重载协议-const\"></a>隐式转换-重载协议-const</h3><p>如果重载的函数参数一样,可以通过转换到某个重载函数,编译会如何哪个版本的选择?<br>(1)类型直接匹配的优先选择;<br>(2)const 类型实参匹配 const 版本<br>(3)非 const 实参优先匹配非 const 版本。<br>没有则隐式转换为 const 版本匹配</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">/* 隐式转换-重载协议-const */</span></span><br><span class=\"line\">…</span><br><span class=\"line\"><span class=\"keyword\">class</span> <span class=\"title class_\">Integer</span> {</span><br><span class=\"line\"><span class=\"type\">int</span> x;</span><br><span class=\"line\"><span class=\"keyword\">public</span>:</span><br><span class=\"line\"><span class=\"built_in\">Integer</span>(<span class=\"type\">int</span> x=<span class=\"number\">0</span>):<span class=\"built_in\">x</span>(x) {}</span><br><span class=\"line\"><span class=\"keyword\">friend</span> ostream& <span class=\"keyword\">operator</span><<(ostream& o, <span class=\"type\">const</span> Integer &hs) {</span><br><span class=\"line\">o << <span class=\"string\">"const "</span> << hs.x;</span><br><span class=\"line\"><span class=\"keyword\">return</span> o;</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"keyword\">friend</span> ostream& <span class=\"keyword\">operator</span><<(ostream& o, Integer &hs) {</span><br><span class=\"line\">o << <span class=\"string\">"no_const "</span> << hs.x ;</span><br><span class=\"line\"><span class=\"keyword\">return</span> o;</span><br><span class=\"line\">}</span><br><span class=\"line\">};</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span><span class=\"params\">()</span> </span>{</span><br><span class=\"line\"><span class=\"function\">Integer <span class=\"title\">i1</span><span class=\"params\">(<span class=\"number\">1</span>)</span></span>;</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">const</span> Integer <span class=\"title\">i2</span><span class=\"params\">(<span class=\"number\">2</span>)</span></span>;</span><br><span class=\"line\">cout << i1 << <span class=\"string\">","</span> << <span class=\"number\">3</span> << <span class=\"string\">","</span> << i2 << endl;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<h3 id=\"explicit\"><a href=\"#explicit\" class=\"headerlink\" title=\"explicit\"></a>explicit</h3><p>C++ 关键字 explicit,用于关闭这种自动类型转化的特性。</p>\n<p>即被 explicit 关键字修饰的类构造函数,不能进行自动地隐式类型转换,只能显式地进行类型转换</p>\n<h3 id=\"隐式转换-nullptr\"><a href=\"#隐式转换-nullptr\" class=\"headerlink\" title=\"隐式转换-nullptr\"></a>隐式转换-nullptr</h3><p>C++ 引入了 nullptr 表示空值指针字面量。</p>\n","excerpt":"","more":"<h1 id=\"运算符重载\"><a href=\"#运算符重载\" class=\"headerlink\" title=\"运算符重载\"></a>运算符重载</h1><p><font color=red><strong>运算符重载的主要目的是:让运算符适用于自定义类型(类或结构体)</strong></font></p>\n<h2 id=\"运算符重载概念\"><a href=\"#运算符重载概念\" class=\"headerlink\" title=\"运算符重载概念\"></a>运算符重载概念</h2><p>运算符重载是<strong>具有特殊函数名的函数</strong>,也具有返回值类型,函数名和参数列表<br>重载的运算符可以理解为带有特殊名称的函数,函数名是由关键字 operator 和其后要重载的运算符符号构成的。</p>\n<h3 id=\"重载的两种方法\"><a href=\"#重载的两种方法\" class=\"headerlink\" title=\"重载的两种方法\"></a>重载的两种方法</h3><p>1.类成员函数运算符重载(类内定义)<br><code>return_type class_name::operator op(operand2) {}</code><br>重载二元运算符时,成员运算符函数只需显式传递一个参数(即二元运算符的右操作数),而左操作数则是该类对象本身,通过<code>this</code>指针隐式传递。</p>\n<p>重载一元运算符时,成员运算符函数没有参数,操作数是该类对象本身,通过<code>this</code>指针隐式传递</p>\n<p>2.友元函数运算符重载(类外定义)<br><code>return_type operator op(operand1, operand2) {}</code></p>\n<p><font color=red><strong>运算符重载至少需要一个操作数是用户定义的类型</strong></font></p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\">MyClass <span class=\"keyword\">operator</span>+(MyClass a, <span class=\"type\">int</span> b); <span class=\"comment\">// 合法(MyClass 是用户定义类型)</span></span><br><span class=\"line\"><span class=\"type\">int</span> <span class=\"keyword\">operator</span>+(<span class=\"type\">int</span> a, <span class=\"type\">int</span> b); <span class=\"comment\">// 非法(两个操作数都是内置类型)</span></span><br></pre></td></tr></table></figure>\n\n<p><font color=red><strong>运算符重载函数 可以返回基本数据类型</strong></font></p>\n<h3 id=\"不可以重载的运算符\"><a href=\"#不可以重载的运算符\" class=\"headerlink\" title=\"不可以重载的运算符\"></a>不可以重载的运算符</h3><p><code>::</code>(作用域解析)<br><code>.</code>(成员访问)<br><code>.*</code>(通过成员指针的成员访问)<br><code>?:</code>(三元条件)<br><code>sizeof</code>:运算符(包括除 new,delete 外的关<br>键字运算符,如 alignof,typeid 等等)</p>\n<p><strong>其他限制:</strong><br>• <strong>不能创建新运算符</strong>,例如 **、<> 或 &|。</p>\n<p>• 运算符 && 与 || 的重载<strong>失去短路求值</strong>。</p>\n<p>• 重载的运算符 -> 必须要么返回裸指针,要么(按引用或值)返回同样重载了运算符 -> 的对象。</p>\n<p>• 不可能更改运算符的<strong>优先级、结合方向或操作数的数量</strong>。</p>\n<h2 id=\"普通运算符重载\"><a href=\"#普通运算符重载\" class=\"headerlink\" title=\"普通运算符重载\"></a>普通运算符重载</h2><p>双目,单目运算符重载<br>例:</p>\n<table>\n<thead>\n<tr>\n<th>运算符名</th>\n<th>类内定义</th>\n<th>类外定义</th>\n</tr>\n</thead>\n<tbody><tr>\n<td>一元加</td>\n<td>T T::operator+() const;</td>\n<td>T operator+(const T& b);</td>\n</tr>\n<tr>\n<td>加法</td>\n<td>T T::operator+(const T& b) const;</td>\n<td>T operator+(const T& b,const T& c);</td>\n</tr>\n</tbody></table>\n<p>部分情况下,需要返回左值对象,可使用 T& 作为返回值。例如 operator<< 和 operator>> 作为流插入和流提取的重载所返回的是 T&</p>\n<h2 id=\"自增-自减运算符重载\"><a href=\"#自增-自减运算符重载\" class=\"headerlink\" title=\"自增/自减运算符重载\"></a>自增/自减运算符重载</h2><p>若为前缀自增运算符,直接重载(以++举例):<br><code>• return_type class_name::operator ++() {}</code></p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\">Integer& <span class=\"keyword\">operator</span> ++ () {</span><br><span class=\"line\">cerr<<<span class=\"string\">"prefix is invoked"</span><<endl;</span><br><span class=\"line\">++x;</span><br><span class=\"line\"><span class=\"keyword\">return</span> *<span class=\"keyword\">this</span>;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<p>• 若为后缀自增运算符,该函数有一个 int 类型的虚拟形参,这个形参在函数的主体中是不会被使用的,这只是一个约定,它告诉编译器递增运算符正在后缀模式下被重载:<br><code>• return_type class_name::operator ++(int) {}</code><br><font color=red>这也是前缀和后缀的主要区分</font></p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\">Integer <span class=\"keyword\">operator</span> ++ (<span class=\"type\">int</span>){</span><br><span class=\"line\">cerr<<<span class=\"string\">"suffix is invoked"</span><<endl;</span><br><span class=\"line\"><span class=\"keyword\">return</span> <span class=\"built_in\">Integer</span>(x++);</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<p><strong>要点:</strong></p>\n<ol>\n<li>内建前缀运算符与后缀运算符原型不一样</li>\n<li>前缀运算符,先增后用,一般返回增后的对象的引用(左值)</li>\n<li>后缀运算符,先用后增,先建立原始对象的副本再自增,一般返回副本对象(右值)</li>\n</ol>\n<h2 id=\"赋值运算符重载\"><a href=\"#赋值运算符重载\" class=\"headerlink\" title=\"赋值运算符重载\"></a>赋值运算符重载</h2><table>\n<thead>\n<tr>\n<th>运算符名</th>\n<th>语法</th>\n<th>类内定义</th>\n<th>类外定义</th>\n</tr>\n</thead>\n<tbody><tr>\n<td>简单赋值</td>\n<td>a=b</td>\n<td>T& T::operator =(const T2& b);</td>\n<td>N/A</td>\n</tr>\n<tr>\n<td>加法赋值</td>\n<td>a+=b</td>\n<td>T& T::operator +=(const T2& b);</td>\n<td>T& operator +=(T& a ,const T2& b);</td>\n</tr>\n</tbody></table>\n<p>注意</p>\n<p>·所有内建赋值运算符都返回<code>*this</code>,而大多数用户定义重载也会返回<code>*this</code>,从而能以与内建版本相同的方式使用用户定义运算符。然而,用户定义运算符重载中,返回类型可以是<font color=red>任意类型</font>包括<code>void</code>。</p>\n<h2 id=\"类型转换符重载\"><a href=\"#类型转换符重载\" class=\"headerlink\" title=\"类型转换符重载\"></a>类型转换符重载</h2><p>基本语法</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"function\"><span class=\"keyword\">operator</span> <span class=\"title\">type</span><span class=\"params\">()</span> <span class=\"type\">const</span> </span>{</span><br><span class=\"line\"> <span class=\"comment\">// 转换逻辑</span></span><br><span class=\"line\"> <span class=\"keyword\">return</span> value;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<p>其中:<br>1.type 是要转换的目标类型 2.必须是成员函数 3.不能指定返回类型(因为返回类型就是 type) 4.通常应该是 const 的,因为它不应该修改对象的状态</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">class</span> <span class=\"title class_\">MyInt</span> {</span><br><span class=\"line\"> <span class=\"type\">int</span> value;</span><br><span class=\"line\"><span class=\"keyword\">public</span>:</span><br><span class=\"line\"> <span class=\"built_in\">MyInt</span>(<span class=\"type\">int</span> v) : <span class=\"built_in\">value</span>(v) {}</span><br><span class=\"line\"> <span class=\"comment\">// 转换为int的类型转换运算符</span></span><br><span class=\"line\"> <span class=\"function\"><span class=\"keyword\">operator</span> <span class=\"title\">int</span><span class=\"params\">()</span> <span class=\"type\">const</span> </span>{</span><br><span class=\"line\"> <span class=\"keyword\">return</span> value;</span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"comment\">// 转换为double的类型转换运算符</span></span><br><span class=\"line\"> <span class=\"function\"><span class=\"keyword\">operator</span> <span class=\"title\">double</span><span class=\"params\">()</span> <span class=\"type\">const</span> </span>{</span><br><span class=\"line\"> <span class=\"keyword\">return</span> <span class=\"built_in\">static_cast</span><<span class=\"type\">double</span>>(value);</span><br><span class=\"line\"> }</span><br><span class=\"line\">};</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span><span class=\"params\">()</span> </span>{</span><br><span class=\"line\"> <span class=\"function\">MyInt <span class=\"title\">mi</span><span class=\"params\">(<span class=\"number\">42</span>)</span></span>;</span><br><span class=\"line\"> <span class=\"type\">int</span> i = mi; <span class=\"comment\">// 隐式调用operator int()</span></span><br><span class=\"line\"> <span class=\"type\">double</span> d = mi; <span class=\"comment\">// 隐式调用operator double()</span></span><br><span class=\"line\"> <span class=\"comment\">// 显式转换</span></span><br><span class=\"line\"> <span class=\"type\">int</span> j = <span class=\"built_in\">static_cast</span><<span class=\"type\">int</span>>(mi);</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<h2 id=\"浅复制与深复制策略\"><a href=\"#浅复制与深复制策略\" class=\"headerlink\" title=\"浅复制与深复制策略\"></a>浅复制与深复制策略</h2><p><strong>浅拷贝赋值</strong><br>• 由缺省的赋值运算符完成,会按成员声明顺序逐一调用成员的赋值运算<br>• 当成员是指针时,被赋值对象与赋值对象共用一个资源</p>\n<p><strong>深拷贝赋值</strong><br>• 由用户定义的的赋值运算符完成。该函数不需要逐一调用非指针成员的赋<br>值运算(但建议按声明顺序逐一赋值)<br>• 当成员是指针时,需要释放已拥有资源,复制赋值对象对应的资源,并指<br>向该资源的副本,即被赋值对象拥有赋值对象资源的副本</p>\n<p><strong>深拷贝策略</strong></p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">class</span> <span class=\"title class_\">IntArray</span> {</span><br><span class=\"line\"><span class=\"type\">int</span> *a;</span><br><span class=\"line\"><span class=\"type\">int</span> n;</span><br><span class=\"line\"><span class=\"keyword\">public</span>:</span><br><span class=\"line\"><span class=\"built_in\">IntArray</span>(<span class=\"type\">int</span> n=<span class=\"number\">1</span>):<span class=\"built_in\">n</span>(n) {</span><br><span class=\"line\">a=<span class=\"keyword\">new</span> <span class=\"type\">int</span>[n];</span><br><span class=\"line\"><span class=\"keyword\">for</span> (<span class=\"type\">int</span> i=<span class=\"number\">0</span>;i<n;++i) a[i]=i;</span><br><span class=\"line\">}</span><br><span class=\"line\">~<span class=\"built_in\">IntArray</span>() {</span><br><span class=\"line\">cout << <span class=\"string\">"release p="</span> << a <<endl;</span><br><span class=\"line\"><span class=\"keyword\">delete</span>[] a;</span><br><span class=\"line\">}</span><br><span class=\"line\">IntArray& <span class=\"keyword\">operator</span> = (<span class=\"type\">const</span> IntArray& other) {</span><br><span class=\"line\"><span class=\"keyword\">if</span> (<span class=\"keyword\">this</span> != &other) {</span><br><span class=\"line\"><span class=\"keyword\">delete</span>[] a; <span class=\"comment\">//这里a一定不为空</span></span><br><span class=\"line\"> n=other.n;</span><br><span class=\"line\">a=<span class=\"keyword\">new</span> <span class=\"type\">int</span>[n];</span><br><span class=\"line\"><span class=\"built_in\">memcpy</span>(a,other.a,<span class=\"built_in\">sizeof</span>(<span class=\"type\">int</span>)*n);</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"keyword\">return</span> *<span class=\"keyword\">this</span>;</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">void</span> <span class=\"title\">print</span><span class=\"params\">()</span> </span>{</span><br><span class=\"line\"><span class=\"keyword\">for</span> (<span class=\"type\">int</span> i=<span class=\"number\">0</span>;i<n;++i) cout<<a[i]<<<span class=\"string\">" "</span>;</span><br><span class=\"line\">cout<<endl;</span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span><span class=\"params\">()</span> </span>{</span><br><span class=\"line\"><span class=\"function\">IntArray <span class=\"title\">a</span><span class=\"params\">(<span class=\"number\">4</span>)</span>, b</span>;</span><br><span class=\"line\">a.<span class=\"built_in\">print</span>();</span><br><span class=\"line\">b=a; <span class=\"comment\">// 调用深拷贝策略赋值</span></span><br><span class=\"line\"> b.<span class=\"built_in\">print</span>();</span><br><span class=\"line\">a.<span class=\"built_in\">print</span>(); <span class=\"comment\">//a,b point to ...</span></span><br><span class=\"line\"><span class=\"keyword\">return</span> <span class=\"number\">0</span>;</span><br><span class=\"line\">}</span><br><span class=\"line\">};</span><br></pre></td></tr></table></figure>\n\n<h2 id=\"下标运算符重载\"><a href=\"#下标运算符重载\" class=\"headerlink\" title=\"下标运算符重载\"></a>下标运算符重载</h2><p><strong>成员访问运算符</strong><br>C++规定,下标运算符[]必须以成员函数的形式进行重载。该重载函数在类中的声明格式如下:</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\">R& T::<span class=\"keyword\">operator</span>[](S b); (<span class=\"number\">1</span>)</span><br><span class=\"line\"><span class=\"type\">const</span> R& T::<span class=\"keyword\">operator</span>[](S b) <span class=\"type\">const</span>; (<span class=\"number\">2</span>)</span><br></pre></td></tr></table></figure>\n\n<p>(1)声明方式,[]不仅可以访问元素,还可以修改元素。<br>(2)声明方式,[]只能访问而不能修改元素。</p>\n<p><strong>在实际开发中,我们应该同时提供以上两种形式,这样做是为了适应 const 对象,因为通过 const 对象只能调用 const 成员函数,如果不提供第二种形式,那么将无法问 const 对象的任何元素。</strong></p>\n<p>例:</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">class</span> <span class=\"title class_\">IntArray</span> {</span><br><span class=\"line\"><span class=\"type\">int</span> *a;</span><br><span class=\"line\"><span class=\"type\">int</span> n;</span><br><span class=\"line\"><span class=\"keyword\">public</span>:</span><br><span class=\"line\"><span class=\"built_in\">IntArray</span>(<span class=\"type\">int</span> n=<span class=\"number\">1</span>):<span class=\"built_in\">n</span>(n) {…}</span><br><span class=\"line\"><span class=\"built_in\">IntArray</span>(<span class=\"type\">const</span> IntArray& other) {…}</span><br><span class=\"line\">~<span class=\"built_in\">IntArray</span>() {…}</span><br><span class=\"line\"><span class=\"type\">int</span>& <span class=\"keyword\">operator</span>[](<span class=\"type\">int</span> i) {</span><br><span class=\"line\"><span class=\"keyword\">if</span> (i>=<span class=\"number\">0</span> && i < n) {</span><br><span class=\"line\"><span class=\"keyword\">return</span> a[i];</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"keyword\">throw</span> std::<span class=\"built_in\">out_of_range</span>(<span class=\"string\">"out of range"</span>);</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"type\">const</span> <span class=\"type\">int</span>& <span class=\"keyword\">operator</span>[](<span class=\"type\">int</span> i) <span class=\"type\">const</span>{</span><br><span class=\"line\"><span class=\"keyword\">if</span> (i>=<span class=\"number\">0</span> && i < n) {</span><br><span class=\"line\"><span class=\"keyword\">return</span> a[i];</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"keyword\">throw</span> std::<span class=\"built_in\">out_of_range</span>(<span class=\"string\">"out of range"</span>);</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">void</span> <span class=\"title\">print</span><span class=\"params\">()</span> <span class=\"type\">const</span> </span>{…</span><br><span class=\"line\">}</span><br><span class=\"line\">};</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span><span class=\"params\">()</span> </span>{</span><br><span class=\"line\"><span class=\"function\">IntArray <span class=\"title\">a</span><span class=\"params\">(<span class=\"number\">4</span>)</span></span>;</span><br><span class=\"line\"><span class=\"keyword\">for</span> (<span class=\"type\">int</span> i=<span class=\"number\">0</span>;i<<span class=\"number\">4</span>;i++) a[i]=i<span class=\"number\">+1</span>;</span><br><span class=\"line\">a.<span class=\"built_in\">print</span>();</span><br><span class=\"line\"><span class=\"comment\">//任务1:以下两个语句,b的哪些成员函数被调用</span></span><br><span class=\"line\"> <span class=\"type\">const</span> IntArray b=a;</span><br><span class=\"line\">cout << <span class=\"string\">"b[0] = "</span> << b[<span class=\"number\">0</span>] <<endl;</span><br><span class=\"line\"><span class=\"comment\">//任务2:print函数去除 const会如何?</span></span><br><span class=\"line\"> b.<span class=\"built_in\">print</span>();</span><br><span class=\"line\"><span class=\"comment\">//任务3:以下语句错误性质一样吗?</span></span><br><span class=\"line\"> <span class=\"comment\">//b[5]=10;</span></span><br><span class=\"line\"><span class=\"comment\">//a[5]=10;</span></span><br><span class=\"line\"><span class=\"keyword\">return</span> <span class=\"number\">0</span>;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<h2 id=\"函数对象\"><a href=\"#函数对象\" class=\"headerlink\" title=\"函数对象\"></a>函数对象</h2><h3 id=\"函数调用\"><a href=\"#函数调用\" class=\"headerlink\" title=\"函数调用\"></a>函数调用</h3><p>函数对象:函数调用 运算符为任何对象提供函数语义。<br>当一个类 T 定义了函数调用,则 T 类型的对象 a 就可以类似函数一样使用 a(…)。 T 也称为函数(callable)类。<br>函数对象<strong>既有对象持有状态的特征,又有函数可调用特征。</strong></p>\n<h3 id=\"无状态\"><a href=\"#无状态\" class=\"headerlink\" title=\"无状态\"></a>无状态</h3><p>当定义的 operator ()函数 没有使用对象的成员时,函数对象调用函数,其表现如同普通函数调用</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">class</span> <span class=\"title class_\">cmp</span> {</span><br><span class=\"line\"><span class=\"keyword\">public</span>:</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">bool</span> <span class=\"title\">operator</span> <span class=\"params\">()</span> <span class=\"params\">(<span class=\"type\">const</span> <span class=\"type\">int</span>& a, <span class=\"type\">const</span> <span class=\"type\">int</span>& b)</span></span></span><br><span class=\"line\"><span class=\"function\"></span>{</span><br><span class=\"line\"><span class=\"keyword\">return</span> a<b;</span><br><span class=\"line\">}</span><br><span class=\"line\">};</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span><span class=\"params\">()</span> </span>{</span><br><span class=\"line\">cmp f;</span><br><span class=\"line\">cout<<<span class=\"built_in\">f</span>(<span class=\"number\">1</span>,<span class=\"number\">2</span>)<<endl;</span><br><span class=\"line\">cout<<<span class=\"built_in\">f</span>(<span class=\"number\">2</span>,<span class=\"number\">1</span>)<<endl;</span><br><span class=\"line\"><span class=\"keyword\">return</span> <span class=\"number\">0</span>;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<h3 id=\"有状态\"><a href=\"#有状态\" class=\"headerlink\" title=\"有状态\"></a>有状态</h3><p>当定义的 operator ()函数使用对象的成员时,函数对象调用函数,其形式如同普通函数调用一般,但其语义变为依赖对象本身内部状态。<strong>同样的函数调用,结果却不同。</strong></p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">class</span> <span class=\"title class_\">GreaterThan</span> {</span><br><span class=\"line\"><span class=\"type\">int</span> baseline;</span><br><span class=\"line\"><span class=\"keyword\">public</span>:</span><br><span class=\"line\"><span class=\"built_in\">GreaterThan</span>(<span class=\"type\">int</span> x):<span class=\"built_in\">baseline</span>(x) { }</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">bool</span> <span class=\"title\">operator</span> <span class=\"params\">()</span> <span class=\"params\">(<span class=\"type\">const</span> <span class=\"type\">int</span>& x)</span> </span>{</span><br><span class=\"line\"><span class=\"keyword\">return</span> x>baseline;</span><br><span class=\"line\">}</span><br><span class=\"line\">};</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span><span class=\"params\">()</span> </span>{</span><br><span class=\"line\"><span class=\"function\">GreaterThan <span class=\"title\">g1</span><span class=\"params\">(<span class=\"number\">10</span>)</span>, <span class=\"title\">g2</span><span class=\"params\">(<span class=\"number\">20</span>)</span></span>;</span><br><span class=\"line\">cout << <span class=\"built_in\">g1</span>(<span class=\"number\">15</span>) << endl;</span><br><span class=\"line\">cout << <span class=\"built_in\">g2</span>(<span class=\"number\">15</span>) << endl;</span><br><span class=\"line\"><span class=\"keyword\">return</span> <span class=\"number\">0</span>;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<h2 id=\"类外定义运算符重载\"><a href=\"#类外定义运算符重载\" class=\"headerlink\" title=\"类外定义运算符重载\"></a>类外定义运算符重载</h2><p>例:</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">struct</span> <span class=\"title class_\">Integer</span> {</span><br><span class=\"line\"><span class=\"type\">int</span> x;</span><br><span class=\"line\"><span class=\"keyword\">public</span>:</span><br><span class=\"line\"><span class=\"built_in\">Integer</span>(<span class=\"type\">int</span> x=<span class=\"number\">0</span>):<span class=\"built_in\">x</span>(x) {}</span><br><span class=\"line\">Integer <span class=\"keyword\">operator</span>- (<span class=\"type\">const</span> Integer& Int) {</span><br><span class=\"line\"><span class=\"keyword\">return</span> <span class=\"built_in\">Integer</span>(x-Int.x);</span><br><span class=\"line\">}</span><br><span class=\"line\">Integer <span class=\"keyword\">operator</span> - () {</span><br><span class=\"line\"><span class=\"keyword\">return</span> <span class=\"built_in\">Integer</span>(-x);</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">void</span> <span class=\"title\">print</span><span class=\"params\">()</span> </span>{</span><br><span class=\"line\">cout<<x<<endl;</span><br><span class=\"line\">}</span><br><span class=\"line\">};</span><br><span class=\"line\">Integer <span class=\"keyword\">operator</span>+(<span class=\"type\">const</span> Integer& lhs,<span class=\"type\">const</span> Integer&</span><br><span class=\"line\">rhs) {</span><br><span class=\"line\"><span class=\"keyword\">return</span> <span class=\"built_in\">Integer</span>(lhs.x+rhs.x);</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span><span class=\"params\">()</span> </span>{</span><br><span class=\"line\">Integer a=<span class=\"number\">3</span>,b,c;</span><br><span class=\"line\"><span class=\"comment\">//任务1:解释两个赋值语句,哪些函数被调用</span></span><br><span class=\"line\"> b = a + <span class=\"number\">4</span>;</span><br><span class=\"line\">c = <span class=\"number\">5</span> + a;</span><br><span class=\"line\">b.<span class=\"built_in\">print</span>();</span><br><span class=\"line\">c.<span class=\"built_in\">print</span>();</span><br><span class=\"line\"><span class=\"comment\">//任务2:将 struct 关键字改为 class</span></span><br><span class=\"line\"><span class=\"keyword\">return</span> <span class=\"number\">0</span>;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<h2 id=\"友元与友元函数\"><a href=\"#友元与友元函数\" class=\"headerlink\" title=\"友元与友元函数\"></a>友元与友元函数</h2><h3 id=\"friend-关键字\"><a href=\"#friend-关键字\" class=\"headerlink\" title=\"friend 关键字\"></a>friend 关键字</h3><p>顾名思义,友元函数就是给“朋友”看的函数,类内部声明 friend 普通函数,函数虽然不属于类,但却可以访问类的变量及函数(<strong>包括私有的</strong>)。<strong>函数需要在类外实现</strong></p>\n<figure class=\"highlight arduino\"><table><tr><td class=\"code\"><pre><span class=\"line\">友元函数(<span class=\"keyword\">friend</span> function)。</span><br><span class=\"line\">• <span class=\"function\"><span class=\"keyword\">friend</span> return_type <span class=\"title\">function_name</span><span class=\"params\">(parameter_type_list)</span></span>;</span><br></pre></td></tr></table></figure>\n\n<h3 id=\"其他类成员函数作为友元\"><a href=\"#其他类成员函数作为友元\" class=\"headerlink\" title=\"其他类成员函数作为友元\"></a>其他类成员函数作为友元</h3><p>类的成员函数也是函数的一种,所以其他类的成员函数也可以是友元函数!</p>\n<p>一个类 A 可以将另一个类 B 声明为自己的友元,那么类 B 的所有成员函数就都可以访问类 A 对象的私有成员<br><code>• friend class B; (在类 A 的内部)</code></p>\n<h2 id=\"操作符重载必须是成员函数的\"><a href=\"#操作符重载必须是成员函数的\" class=\"headerlink\" title=\"操作符重载必须是成员函数的\"></a>操作符重载必须是成员函数的</h2><figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\">a=b</span><br><span class=\"line\"><span class=\"built_in\">a</span>(b...)</span><br><span class=\"line\">a[b]</span><br><span class=\"line\">a-></span><br></pre></td></tr></table></figure>\n\n<h2 id=\"重载匹配与隐式转换\"><a href=\"#重载匹配与隐式转换\" class=\"headerlink\" title=\"重载匹配与隐式转换\"></a>重载匹配与隐式转换</h2><h3 id=\"对象隐式转换\"><a href=\"#对象隐式转换\" class=\"headerlink\" title=\"对象隐式转换\"></a>对象隐式转换</h3><p><strong>如果对象 T 存在构造函数 T(T1),则 T1 类型对象(实参)可隐式转为 T 类型对象(形参)</strong></p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">class</span> <span class=\"title class_\">Integer</span> {</span><br><span class=\"line\"><span class=\"type\">int</span> x;</span><br><span class=\"line\"><span class=\"keyword\">public</span>:</span><br><span class=\"line\"><span class=\"built_in\">Integer</span>(<span class=\"type\">int</span> x=<span class=\"number\">0</span>):<span class=\"built_in\">x</span>(x) {}</span><br><span class=\"line\"><span class=\"keyword\">friend</span> Integer <span class=\"keyword\">operator</span>+(<span class=\"type\">const</span> Integer &lhs,<span class=\"type\">const</span> Integer &rhs){</span><br><span class=\"line\"><span class=\"keyword\">return</span> lhs.x + rhs.x;</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"keyword\">friend</span> ostream& <span class=\"keyword\">operator</span><<(ostream& o, <span class=\"type\">const</span> Integer &hs) {</span><br><span class=\"line\">o << hs.x;</span><br><span class=\"line\"><span class=\"keyword\">return</span> o;</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span><span class=\"params\">()</span> </span>{</span><br><span class=\"line\">string s;</span><br><span class=\"line\">s = <span class=\"string\">"Hello"</span>;</span><br><span class=\"line\">cout << s << endl;</span><br><span class=\"line\"><span class=\"function\">Integer <span class=\"title\">i1</span><span class=\"params\">(<span class=\"number\">3</span>)</span>, i2</span>;</span><br><span class=\"line\">i2 = <span class=\"number\">1.1</span> + i1;</span><br><span class=\"line\">cout << i2 << endl;</span><br><span class=\"line\">}</span><br><span class=\"line\">};</span><br></pre></td></tr></table></figure>\n\n<h3 id=\"隐式转换-重载协议-const\"><a href=\"#隐式转换-重载协议-const\" class=\"headerlink\" title=\"隐式转换-重载协议-const\"></a>隐式转换-重载协议-const</h3><p>如果重载的函数参数一样,可以通过转换到某个重载函数,编译会如何哪个版本的选择?<br>(1)类型直接匹配的优先选择;<br>(2)const 类型实参匹配 const 版本<br>(3)非 const 实参优先匹配非 const 版本。<br>没有则隐式转换为 const 版本匹配</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">/* 隐式转换-重载协议-const */</span></span><br><span class=\"line\">…</span><br><span class=\"line\"><span class=\"keyword\">class</span> <span class=\"title class_\">Integer</span> {</span><br><span class=\"line\"><span class=\"type\">int</span> x;</span><br><span class=\"line\"><span class=\"keyword\">public</span>:</span><br><span class=\"line\"><span class=\"built_in\">Integer</span>(<span class=\"type\">int</span> x=<span class=\"number\">0</span>):<span class=\"built_in\">x</span>(x) {}</span><br><span class=\"line\"><span class=\"keyword\">friend</span> ostream& <span class=\"keyword\">operator</span><<(ostream& o, <span class=\"type\">const</span> Integer &hs) {</span><br><span class=\"line\">o << <span class=\"string\">"const "</span> << hs.x;</span><br><span class=\"line\"><span class=\"keyword\">return</span> o;</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"keyword\">friend</span> ostream& <span class=\"keyword\">operator</span><<(ostream& o, Integer &hs) {</span><br><span class=\"line\">o << <span class=\"string\">"no_const "</span> << hs.x ;</span><br><span class=\"line\"><span class=\"keyword\">return</span> o;</span><br><span class=\"line\">}</span><br><span class=\"line\">};</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span><span class=\"params\">()</span> </span>{</span><br><span class=\"line\"><span class=\"function\">Integer <span class=\"title\">i1</span><span class=\"params\">(<span class=\"number\">1</span>)</span></span>;</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">const</span> Integer <span class=\"title\">i2</span><span class=\"params\">(<span class=\"number\">2</span>)</span></span>;</span><br><span class=\"line\">cout << i1 << <span class=\"string\">","</span> << <span class=\"number\">3</span> << <span class=\"string\">","</span> << i2 << endl;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<h3 id=\"explicit\"><a href=\"#explicit\" class=\"headerlink\" title=\"explicit\"></a>explicit</h3><p>C++ 关键字 explicit,用于关闭这种自动类型转化的特性。</p>\n<p>即被 explicit 关键字修饰的类构造函数,不能进行自动地隐式类型转换,只能显式地进行类型转换</p>\n<h3 id=\"隐式转换-nullptr\"><a href=\"#隐式转换-nullptr\" class=\"headerlink\" title=\"隐式转换-nullptr\"></a>隐式转换-nullptr</h3><p>C++ 引入了 nullptr 表示空值指针字面量。</p>\n"},{"title":"初试C++ 2.0","top_img":"transparent","comments":0,"_content":"\n# 初学 C++\n\n---\n\n## string 类与操作\n\n### 初识类\n\n**类是现实世界或抽象世界中概念,是关于同类事物定义的描述**\n\n在标准库中有很多类,通过以下类可体验与 C 语言的不同\n• < string >库中的`std::string` 类\n• 输入/输出库中的 `std::ifstream, std::ofstream` 类\n\n### string 类 与 C 风格字符串\n\nC 风格字符串的缺点:\n\n1.C 风格字符串是使用 null 字符 '\\0' 终止的一维字符数组。因而字符串定义时,必须事先知道保留多大空间存储字符串\n\n2.在字符串操作,如 strcat,时要保证目标字符串有足够的空间\n\n3.使用 malloc 动态空间处理字符串,对一般程序员来说太复杂,非常容易出现\nBUG\n\n### 创建 string\n\n```cpp\nstring s1;\nstring s2 = \"c++\";\nstring s3 = s2;\nstring s4 (5, 's');//s4 初始化为 5 个 s\n```\n\n### string 对象的运算\n\n`string` 类实现了以下运算符的重载\n\n1.联接运算:`operator+`,连接两个字符串或者一个字符串和一个字符\n\n2.比较运算:`operator,<,<=,>,>=,<=>`(c++20 起),以字典序比较两个字符串(关系运算符)\n\n3.下标运算:`operator[]`,访问指定字符,返回指定字符引用,即可作为左值\n\n4.赋值运算:`operator=,+=`,右操作数可以是字符串,字符,C 字符串,字符数组\n\nps:字符串比较运算符`==,!=`的作用是:逐字符比较两个字符串内容\n\n### string 对象的操作\n\n#### 函数重载\n\nC++ 则允许多个函数拥有相同的名字,只要它们的参数列表不同就可以,这就是函数的重载\n\n```\n以 string 对象的 find 函数为例:\n• s.find(str) 在 s 中查找子串 str\n• s.find(\"hello\",3) 在s中从第4个位置开始查找子串\"hello\"\n• s.find('H')在 s 中查找字符'H'\n```\n\n#### 基本操作\n\n**`length()` 返回类型 `size_t` 的字符串的长度**\n\n**`c_str()` 返回类型 `const char \\*` 的 C 风格字符串。以 null 结束**\n例:\n\n```cpp\n/* str-method-basic.cpp */\n#include<iostream>\n#include<string>\nusing namespace std;\nint main() {\nstring s = \"sysu-computer\";\nint len = s.length();\nconst char* cs = s.c_str();\ncout << cs << \" len is \"\n<< len << endl;\nreturn 0;\n}\n```\n\n#### 查找、替换\n\n**`find(string|char\\*|char s [,int pos=0])` 寻找首个等于给定字符序列的子串。搜索始于 pos,返回类型 size_t 的位置。rfind 从右边开始搜索**\n\n**`replace(int pos, int count, string|char\\*|char s)` 替换指定范围内容**\n例:\n\n```cpp\n/* str-method-find.cpp */\n#include<iostream>\n#include<string>\nusing namespace std;\nint main() {\nstring s = \"sysu-computer\";\nint pos = s.find(\"computer\");\ns.replace(pos,8,\"software\");\ncout << s << endl;\nreturn 0;\n}\n```\n\n#### 添加,插入,删除\n\n`append(string)` 后附 string str\n\n`append(int count, char ch)` 后 附 count 个字符 ch\n\n`insert(int index, int count, char ch)` 在 index 位置插入 count 个 ch\n\n`insert(int index, string|char\\* s)` 在 index 位置插入 s\n\n`erase(int index, int count)` 删 除 从 index 开始的 count 个字符\n\n`clear()` 清空\n注:clear() 仅清空字符串中的有效字符(即 size() 变为 0),但不会释放已分配的内存空间。这意味着 capacity()(预分配的内存容量)不会改变\n\n例:\n\n```cpp\n/* str-method-insert.cpp */\n#include<iostream>\n#include<string>\nusing namespace std;\nint main() {\nstring s = \"ysu\";\ns.insert(0,1,'S').append(1,'-').append(\"Xcomputer\");\ns.erase(5,1);\ncout << s << endl;\nreturn 0;\n}\n```\n\n#### 子串、比较、拷贝、交换\n\n• `substr(int pos, int count)` 返回子串对\n象\n\n• `compare(string|char\\* str)` 与 str 比较,\n返回 1,0,-1 之一\n\n• `compare(int pos, int count`,\nstring|char\\* str) 字串与 str 比较,返回\n1,0,-1 之一\ncompare 用于比较两个字符串的字典序关系\n\n• `copy(string|char\\* dest, int pos, int\ncount)` 将子串复制到目标对象\n\n• `swap(string other)` 与 other 交换内容\n\n例:\n\n```cpp\n/* str-method-substr.cpp */\n#include<iostream>\n#include<string>\nusing namespace std;\nint main() {\nstring s = \"Sysu-Computer\";\ncout << s.substr(0,4) << \" \";\nif (s.compare(5,8,\"Computer\")==0) {\ncout << \"OK!\" << endl;\n}\nreturn 0;\n}\n```\n\n```cpp\n#include <iostream>\n#include <algorithm>\nusing namespace std;\nint main() {\n int a = 5, b = 10;\n cout << \"交换前:a=\" << a << \", b=\" << b << endl;\n swap(a, b); // 直接调用标准库的swap函数\n cout << \"交换后:a=\" << a << \", b=\" << b << endl;\n return 0;\n}\n```\n\n## 使用 C 标准库\n\nC 标准库,即不仅可以用 g++ 编译 c 风格的 cpp 程序,也可以使用 C 库函数\n\n## const & constexpr\n\nconst :\n• 限定为不可修改(只读)变量\n• 限定作为常量或字面量\n\nconstexpr :\n声明编译时可以对函数或变量求值。\n• 限定为常量表达式\n• 限定为编译时可优化执行的函数\n\n```cpp\nconstexpr int d() { return 40; }\n```\n\nconstexpr 函数允许返回编译期常量。此处返回 40 是合法的常量表达式,且函数体符合 constexpr 的语法要求\n\n**即凡是表达“只读”语义的场景都使用 const,表达“常量”语义的场景都使用 constexpr**\n\n## auto,bool 关键字\n\n### auto\n\nauto 的原理就是根据初始化的表达式,在编译期间根据表达式类型自动推\n导出对象的类型。\n\n```cpp\nauto x1 = 5; 等价于 int x1 = 5;\n```\n\n注意点: 1.用 auto 声明的变量必须初始化 2.函数和模板参数不能被声明为 auto 3.因为 auto 是一个占位符,并不是一个他自己的类型,因此不能用于类型转换或其\n他一些操作,如 sizeof 和 typeid 4.定义在一个 auto 序列的变量必须始终推导成同一类型\n\n```cpp\nauto x1 = 5,x2 = 5.0,x3='r'; //这样写是不合法的,因为各个变量类型不同\n```\n\n### bool\n\nbool - 是存放两个值 true 或 false 之一的类型。\n\n#### 初始化\n\n```cpp\nbool flag = false;\nbool flag = 1;\n```\n\n#### 隐式转换规则 \n\n任何非零的整型值(无论是正数还是负数)在转换为布尔型时都会变为 true,而零值会转换为 false。因此,-5 作为非零整数,赋值给布尔变量时会得到 true\n\n# 理论题\n\n## typeid 操作符\n\n### 1. 获取类型信息\n\n```cpp\nfloat f = 1.1f;\nstd::cout << typeid(f).name(); // 可能输出\"float\"(依赖编译器实现)\n```\n\n### 2.类型检查与比较\n\n```cpp\nBase* ptr = new Derived();\nif (typeid(*ptr) == typeid(Derived)) { // 若Base是多态类(含虚函数)\n// 执行派生类相关逻辑\n}\n```\n\n## empty 函数\n\n判断字符串是否为空的成员函数\n\n```cpp\nstd::string s = \"\";\nif (s.empty()) {\n std::cout << \"字符串为空\";\n}\n```\n\n## find\n\n当 find()方法找不到子串时返回:**`string::npos`**\n\nstring::find()的返回值类型是 size_type(无符号整型),而非简单的 intbool。当查找失败时,它不会返回-1 或 false,而是返回一个特殊常量 string::npos\n\n## 范围 for 循环\n\n范围 for 循环遍历字符串 str 中每个字符\n\n```cpp\nfor(char c : str) {\n cout << c; }\n```\n\n## 双引号 \" \" 与 单引号 ' '\n\n### 双引号 \"\"\n\n双引号 \"\":字符串字面量(String Literal)\n用途:表示一个字符串(多个字符组成的序列)。\n\n类型:`const char\\*(C 风格字符串)或隐式转换为 std::string`\n\n```cpp\nconst char* s1 = \"Hello\"; // C风格字符串\nstd::string s2 = \"World\"; // C++字符串对象\n```\n\n### 单引号 ''\n\n单引号 '':字符字面量(Character Literal)\n用途:表示一个单个字符。\n\n类型:`char。`\n[========]\n\n[========]\n\n内存表示:仅存储单个字符的 ASCII 值。\n\n```cpp\nchar c1 = 'A'; // 正确\nchar c2 = '\\n'; // 正确(转义字符)\n// char c3 = 'AB'; // 错误:单引号内只能有一个字符\n```\n\n注:**混淆二者会导致编译错误或逻辑错误。**\n\n错误 1:单引号包裹多个字符\n\n```cpp\nchar c = 'AB'; // 编译错误!单引号内只能有一个字符\n```\n\n错误 2:混淆字符和字符串比较\n\n```cpp\nstd::string s = \"A\";\nif (s == 'A') { // 错误!'A'是char,s是std::string\n // ...\n}\n// 正确写法:if (s == \"A\") 或 if (s[0] == 'A')\n```\n\n错误 3:误用双引号初始化 char\n\n```cpp\nchar c = \"A\"; // 错误!\"A\"是const char*,无法赋值给char\n// 正确写法:char c = 'A';\n```\n\n## vector 容器\n\n等待填坑\n","source":"_posts/second-blog.md","raw":"---\ntitle: 初试C++ 2.0\ntags: C++\ntop_img: transparent\ncomments: false\n---\n\n# 初学 C++\n\n---\n\n## string 类与操作\n\n### 初识类\n\n**类是现实世界或抽象世界中概念,是关于同类事物定义的描述**\n\n在标准库中有很多类,通过以下类可体验与 C 语言的不同\n• < string >库中的`std::string` 类\n• 输入/输出库中的 `std::ifstream, std::ofstream` 类\n\n### string 类 与 C 风格字符串\n\nC 风格字符串的缺点:\n\n1.C 风格字符串是使用 null 字符 '\\0' 终止的一维字符数组。因而字符串定义时,必须事先知道保留多大空间存储字符串\n\n2.在字符串操作,如 strcat,时要保证目标字符串有足够的空间\n\n3.使用 malloc 动态空间处理字符串,对一般程序员来说太复杂,非常容易出现\nBUG\n\n### 创建 string\n\n```cpp\nstring s1;\nstring s2 = \"c++\";\nstring s3 = s2;\nstring s4 (5, 's');//s4 初始化为 5 个 s\n```\n\n### string 对象的运算\n\n`string` 类实现了以下运算符的重载\n\n1.联接运算:`operator+`,连接两个字符串或者一个字符串和一个字符\n\n2.比较运算:`operator,<,<=,>,>=,<=>`(c++20 起),以字典序比较两个字符串(关系运算符)\n\n3.下标运算:`operator[]`,访问指定字符,返回指定字符引用,即可作为左值\n\n4.赋值运算:`operator=,+=`,右操作数可以是字符串,字符,C 字符串,字符数组\n\nps:字符串比较运算符`==,!=`的作用是:逐字符比较两个字符串内容\n\n### string 对象的操作\n\n#### 函数重载\n\nC++ 则允许多个函数拥有相同的名字,只要它们的参数列表不同就可以,这就是函数的重载\n\n```\n以 string 对象的 find 函数为例:\n• s.find(str) 在 s 中查找子串 str\n• s.find(\"hello\",3) 在s中从第4个位置开始查找子串\"hello\"\n• s.find('H')在 s 中查找字符'H'\n```\n\n#### 基本操作\n\n**`length()` 返回类型 `size_t` 的字符串的长度**\n\n**`c_str()` 返回类型 `const char \\*` 的 C 风格字符串。以 null 结束**\n例:\n\n```cpp\n/* str-method-basic.cpp */\n#include<iostream>\n#include<string>\nusing namespace std;\nint main() {\nstring s = \"sysu-computer\";\nint len = s.length();\nconst char* cs = s.c_str();\ncout << cs << \" len is \"\n<< len << endl;\nreturn 0;\n}\n```\n\n#### 查找、替换\n\n**`find(string|char\\*|char s [,int pos=0])` 寻找首个等于给定字符序列的子串。搜索始于 pos,返回类型 size_t 的位置。rfind 从右边开始搜索**\n\n**`replace(int pos, int count, string|char\\*|char s)` 替换指定范围内容**\n例:\n\n```cpp\n/* str-method-find.cpp */\n#include<iostream>\n#include<string>\nusing namespace std;\nint main() {\nstring s = \"sysu-computer\";\nint pos = s.find(\"computer\");\ns.replace(pos,8,\"software\");\ncout << s << endl;\nreturn 0;\n}\n```\n\n#### 添加,插入,删除\n\n`append(string)` 后附 string str\n\n`append(int count, char ch)` 后 附 count 个字符 ch\n\n`insert(int index, int count, char ch)` 在 index 位置插入 count 个 ch\n\n`insert(int index, string|char\\* s)` 在 index 位置插入 s\n\n`erase(int index, int count)` 删 除 从 index 开始的 count 个字符\n\n`clear()` 清空\n注:clear() 仅清空字符串中的有效字符(即 size() 变为 0),但不会释放已分配的内存空间。这意味着 capacity()(预分配的内存容量)不会改变\n\n例:\n\n```cpp\n/* str-method-insert.cpp */\n#include<iostream>\n#include<string>\nusing namespace std;\nint main() {\nstring s = \"ysu\";\ns.insert(0,1,'S').append(1,'-').append(\"Xcomputer\");\ns.erase(5,1);\ncout << s << endl;\nreturn 0;\n}\n```\n\n#### 子串、比较、拷贝、交换\n\n• `substr(int pos, int count)` 返回子串对\n象\n\n• `compare(string|char\\* str)` 与 str 比较,\n返回 1,0,-1 之一\n\n• `compare(int pos, int count`,\nstring|char\\* str) 字串与 str 比较,返回\n1,0,-1 之一\ncompare 用于比较两个字符串的字典序关系\n\n• `copy(string|char\\* dest, int pos, int\ncount)` 将子串复制到目标对象\n\n• `swap(string other)` 与 other 交换内容\n\n例:\n\n```cpp\n/* str-method-substr.cpp */\n#include<iostream>\n#include<string>\nusing namespace std;\nint main() {\nstring s = \"Sysu-Computer\";\ncout << s.substr(0,4) << \" \";\nif (s.compare(5,8,\"Computer\")==0) {\ncout << \"OK!\" << endl;\n}\nreturn 0;\n}\n```\n\n```cpp\n#include <iostream>\n#include <algorithm>\nusing namespace std;\nint main() {\n int a = 5, b = 10;\n cout << \"交换前:a=\" << a << \", b=\" << b << endl;\n swap(a, b); // 直接调用标准库的swap函数\n cout << \"交换后:a=\" << a << \", b=\" << b << endl;\n return 0;\n}\n```\n\n## 使用 C 标准库\n\nC 标准库,即不仅可以用 g++ 编译 c 风格的 cpp 程序,也可以使用 C 库函数\n\n## const & constexpr\n\nconst :\n• 限定为不可修改(只读)变量\n• 限定作为常量或字面量\n\nconstexpr :\n声明编译时可以对函数或变量求值。\n• 限定为常量表达式\n• 限定为编译时可优化执行的函数\n\n```cpp\nconstexpr int d() { return 40; }\n```\n\nconstexpr 函数允许返回编译期常量。此处返回 40 是合法的常量表达式,且函数体符合 constexpr 的语法要求\n\n**即凡是表达“只读”语义的场景都使用 const,表达“常量”语义的场景都使用 constexpr**\n\n## auto,bool 关键字\n\n### auto\n\nauto 的原理就是根据初始化的表达式,在编译期间根据表达式类型自动推\n导出对象的类型。\n\n```cpp\nauto x1 = 5; 等价于 int x1 = 5;\n```\n\n注意点: 1.用 auto 声明的变量必须初始化 2.函数和模板参数不能被声明为 auto 3.因为 auto 是一个占位符,并不是一个他自己的类型,因此不能用于类型转换或其\n他一些操作,如 sizeof 和 typeid 4.定义在一个 auto 序列的变量必须始终推导成同一类型\n\n```cpp\nauto x1 = 5,x2 = 5.0,x3='r'; //这样写是不合法的,因为各个变量类型不同\n```\n\n### bool\n\nbool - 是存放两个值 true 或 false 之一的类型。\n\n#### 初始化\n\n```cpp\nbool flag = false;\nbool flag = 1;\n```\n\n#### 隐式转换规则 \n\n任何非零的整型值(无论是正数还是负数)在转换为布尔型时都会变为 true,而零值会转换为 false。因此,-5 作为非零整数,赋值给布尔变量时会得到 true\n\n# 理论题\n\n## typeid 操作符\n\n### 1. 获取类型信息\n\n```cpp\nfloat f = 1.1f;\nstd::cout << typeid(f).name(); // 可能输出\"float\"(依赖编译器实现)\n```\n\n### 2.类型检查与比较\n\n```cpp\nBase* ptr = new Derived();\nif (typeid(*ptr) == typeid(Derived)) { // 若Base是多态类(含虚函数)\n// 执行派生类相关逻辑\n}\n```\n\n## empty 函数\n\n判断字符串是否为空的成员函数\n\n```cpp\nstd::string s = \"\";\nif (s.empty()) {\n std::cout << \"字符串为空\";\n}\n```\n\n## find\n\n当 find()方法找不到子串时返回:**`string::npos`**\n\nstring::find()的返回值类型是 size_type(无符号整型),而非简单的 intbool。当查找失败时,它不会返回-1 或 false,而是返回一个特殊常量 string::npos\n\n## 范围 for 循环\n\n范围 for 循环遍历字符串 str 中每个字符\n\n```cpp\nfor(char c : str) {\n cout << c; }\n```\n\n## 双引号 \" \" 与 单引号 ' '\n\n### 双引号 \"\"\n\n双引号 \"\":字符串字面量(String Literal)\n用途:表示一个字符串(多个字符组成的序列)。\n\n类型:`const char\\*(C 风格字符串)或隐式转换为 std::string`\n\n```cpp\nconst char* s1 = \"Hello\"; // C风格字符串\nstd::string s2 = \"World\"; // C++字符串对象\n```\n\n### 单引号 ''\n\n单引号 '':字符字面量(Character Literal)\n用途:表示一个单个字符。\n\n类型:`char。`\n[========]\n\n[========]\n\n内存表示:仅存储单个字符的 ASCII 值。\n\n```cpp\nchar c1 = 'A'; // 正确\nchar c2 = '\\n'; // 正确(转义字符)\n// char c3 = 'AB'; // 错误:单引号内只能有一个字符\n```\n\n注:**混淆二者会导致编译错误或逻辑错误。**\n\n错误 1:单引号包裹多个字符\n\n```cpp\nchar c = 'AB'; // 编译错误!单引号内只能有一个字符\n```\n\n错误 2:混淆字符和字符串比较\n\n```cpp\nstd::string s = \"A\";\nif (s == 'A') { // 错误!'A'是char,s是std::string\n // ...\n}\n// 正确写法:if (s == \"A\") 或 if (s[0] == 'A')\n```\n\n错误 3:误用双引号初始化 char\n\n```cpp\nchar c = \"A\"; // 错误!\"A\"是const char*,无法赋值给char\n// 正确写法:char c = 'A';\n```\n\n## vector 容器\n\n等待填坑\n","slug":"second-blog","published":1,"date":"2025-03-05T11:51:31.344Z","updated":"2025-03-05T13:24:34.401Z","layout":"post","photos":[],"_id":"cmkmd8tyz000kcw649dly5vw2","content":"<link rel=\"stylesheet\" class=\"aplayer-secondary-style-marker\" href=\"\\assets\\css\\APlayer.min.css\"><script src=\"\\assets\\js\\APlayer.min.js\" class=\"aplayer-secondary-script-marker\"></script><h1 id=\"初学-C\"><a href=\"#初学-C\" class=\"headerlink\" title=\"初学 C++\"></a>初学 C++</h1><hr>\n<h2 id=\"string-类与操作\"><a href=\"#string-类与操作\" class=\"headerlink\" title=\"string 类与操作\"></a>string 类与操作</h2><h3 id=\"初识类\"><a href=\"#初识类\" class=\"headerlink\" title=\"初识类\"></a>初识类</h3><p><strong>类是现实世界或抽象世界中概念,是关于同类事物定义的描述</strong></p>\n<p>在标准库中有很多类,通过以下类可体验与 C 语言的不同<br>• < string >库中的<code>std::string</code> 类<br>• 输入/输出库中的 <code>std::ifstream, std::ofstream</code> 类</p>\n<h3 id=\"string-类-与-C-风格字符串\"><a href=\"#string-类-与-C-风格字符串\" class=\"headerlink\" title=\"string 类 与 C 风格字符串\"></a>string 类 与 C 风格字符串</h3><p>C 风格字符串的缺点:</p>\n<p>1.C 风格字符串是使用 null 字符 ‘\\0’ 终止的一维字符数组。因而字符串定义时,必须事先知道保留多大空间存储字符串</p>\n<p>2.在字符串操作,如 strcat,时要保证目标字符串有足够的空间</p>\n<p>3.使用 malloc 动态空间处理字符串,对一般程序员来说太复杂,非常容易出现<br>BUG</p>\n<h3 id=\"创建-string\"><a href=\"#创建-string\" class=\"headerlink\" title=\"创建 string\"></a>创建 string</h3><figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\">string s1;</span><br><span class=\"line\">string s2 = <span class=\"string\">"c++"</span>;</span><br><span class=\"line\">string s3 = s2;</span><br><span class=\"line\"><span class=\"function\">string <span class=\"title\">s4</span> <span class=\"params\">(<span class=\"number\">5</span>, <span class=\"string\">'s'</span>)</span></span>;<span class=\"comment\">//s4 初始化为 5 个 s</span></span><br></pre></td></tr></table></figure>\n\n<h3 id=\"string-对象的运算\"><a href=\"#string-对象的运算\" class=\"headerlink\" title=\"string 对象的运算\"></a>string 对象的运算</h3><p><code>string</code> 类实现了以下运算符的重载</p>\n<p>1.联接运算:<code>operator+</code>,连接两个字符串或者一个字符串和一个字符</p>\n<p>2.比较运算:<code>operator,<,<=,>,>=,<=></code>(c++20 起),以字典序比较两个字符串(关系运算符)</p>\n<p>3.下标运算:<code>operator[]</code>,访问指定字符,返回指定字符引用,即可作为左值</p>\n<p>4.赋值运算:<code>operator=,+=</code>,右操作数可以是字符串,字符,C 字符串,字符数组</p>\n<p>ps:字符串比较运算符<code>==,!=</code>的作用是:逐字符比较两个字符串内容</p>\n<h3 id=\"string-对象的操作\"><a href=\"#string-对象的操作\" class=\"headerlink\" title=\"string 对象的操作\"></a>string 对象的操作</h3><h4 id=\"函数重载\"><a href=\"#函数重载\" class=\"headerlink\" title=\"函数重载\"></a>函数重载</h4><p>C++ 则允许多个函数拥有相同的名字,只要它们的参数列表不同就可以,这就是函数的重载</p>\n<figure class=\"highlight routeros\"><table><tr><td class=\"code\"><pre><span class=\"line\">以 string 对象的 <span class=\"built_in\">find</span> 函数为例:</span><br><span class=\"line\">• s.<span class=\"built_in\">find</span>(str) 在 s 中查找子串 str</span><br><span class=\"line\">• s.<span class=\"built_in\">find</span>(<span class=\"string\">"hello"</span>,3) 在s中从第4个位置开始查找子串<span class=\"string\">"hello"</span></span><br><span class=\"line\">• s.<span class=\"built_in\">find</span>(<span class=\"string\">'H'</span>)在 s 中查找字符<span class=\"string\">'H'</span></span><br></pre></td></tr></table></figure>\n\n<h4 id=\"基本操作\"><a href=\"#基本操作\" class=\"headerlink\" title=\"基本操作\"></a>基本操作</h4><p><strong><code>length()</code> 返回类型 <code>size_t</code> 的字符串的长度</strong></p>\n<p><strong><code>c_str()</code> 返回类型 <code>const char \\*</code> 的 C 风格字符串。以 null 结束</strong><br>例:</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">/* str-method-basic.cpp */</span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span><span class=\"string\"><iostream></span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span><span class=\"string\"><string></span></span></span><br><span class=\"line\"><span class=\"keyword\">using</span> <span class=\"keyword\">namespace</span> std;</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span><span class=\"params\">()</span> </span>{</span><br><span class=\"line\">string s = <span class=\"string\">"sysu-computer"</span>;</span><br><span class=\"line\"><span class=\"type\">int</span> len = s.<span class=\"built_in\">length</span>();</span><br><span class=\"line\"><span class=\"type\">const</span> <span class=\"type\">char</span>* cs = s.<span class=\"built_in\">c_str</span>();</span><br><span class=\"line\">cout << cs << <span class=\"string\">" len is "</span></span><br><span class=\"line\"><< len << endl;</span><br><span class=\"line\"><span class=\"keyword\">return</span> <span class=\"number\">0</span>;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<h4 id=\"查找、替换\"><a href=\"#查找、替换\" class=\"headerlink\" title=\"查找、替换\"></a>查找、替换</h4><p><strong><code>find(string|char\\*|char s [,int pos=0])</code> 寻找首个等于给定字符序列的子串。搜索始于 pos,返回类型 size_t 的位置。rfind 从右边开始搜索</strong></p>\n<p><strong><code>replace(int pos, int count, string|char\\*|char s)</code> 替换指定范围内容</strong><br>例:</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">/* str-method-find.cpp */</span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span><span class=\"string\"><iostream></span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span><span class=\"string\"><string></span></span></span><br><span class=\"line\"><span class=\"keyword\">using</span> <span class=\"keyword\">namespace</span> std;</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span><span class=\"params\">()</span> </span>{</span><br><span class=\"line\">string s = <span class=\"string\">"sysu-computer"</span>;</span><br><span class=\"line\"><span class=\"type\">int</span> pos = s.<span class=\"built_in\">find</span>(<span class=\"string\">"computer"</span>);</span><br><span class=\"line\">s.<span class=\"built_in\">replace</span>(pos,<span class=\"number\">8</span>,<span class=\"string\">"software"</span>);</span><br><span class=\"line\">cout << s << endl;</span><br><span class=\"line\"><span class=\"keyword\">return</span> <span class=\"number\">0</span>;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<h4 id=\"添加,插入,删除\"><a href=\"#添加,插入,删除\" class=\"headerlink\" title=\"添加,插入,删除\"></a>添加,插入,删除</h4><p><code>append(string)</code> 后附 string str</p>\n<p><code>append(int count, char ch)</code> 后 附 count 个字符 ch</p>\n<p><code>insert(int index, int count, char ch)</code> 在 index 位置插入 count 个 ch</p>\n<p><code>insert(int index, string|char\\* s)</code> 在 index 位置插入 s</p>\n<p><code>erase(int index, int count)</code> 删 除 从 index 开始的 count 个字符</p>\n<p><code>clear()</code> 清空<br>注:clear() 仅清空字符串中的有效字符(即 size() 变为 0),但不会释放已分配的内存空间。这意味着 capacity()(预分配的内存容量)不会改变</p>\n<p>例:</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">/* str-method-insert.cpp */</span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span><span class=\"string\"><iostream></span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span><span class=\"string\"><string></span></span></span><br><span class=\"line\"><span class=\"keyword\">using</span> <span class=\"keyword\">namespace</span> std;</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span><span class=\"params\">()</span> </span>{</span><br><span class=\"line\">string s = <span class=\"string\">"ysu"</span>;</span><br><span class=\"line\">s.<span class=\"built_in\">insert</span>(<span class=\"number\">0</span>,<span class=\"number\">1</span>,<span class=\"string\">'S'</span>).<span class=\"built_in\">append</span>(<span class=\"number\">1</span>,<span class=\"string\">'-'</span>).<span class=\"built_in\">append</span>(<span class=\"string\">"Xcomputer"</span>);</span><br><span class=\"line\">s.<span class=\"built_in\">erase</span>(<span class=\"number\">5</span>,<span class=\"number\">1</span>);</span><br><span class=\"line\">cout << s << endl;</span><br><span class=\"line\"><span class=\"keyword\">return</span> <span class=\"number\">0</span>;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<h4 id=\"子串、比较、拷贝、交换\"><a href=\"#子串、比较、拷贝、交换\" class=\"headerlink\" title=\"子串、比较、拷贝、交换\"></a>子串、比较、拷贝、交换</h4><p>• <code>substr(int pos, int count)</code> 返回子串对<br>象</p>\n<p>• <code>compare(string|char\\* str)</code> 与 str 比较,<br>返回 1,0,-1 之一</p>\n<p>• <code>compare(int pos, int count</code>,<br>string|char* str) 字串与 str 比较,返回<br>1,0,-1 之一<br>compare 用于比较两个字符串的字典序关系</p>\n<p>• <code>copy(string|char\\* dest, int pos, int count)</code> 将子串复制到目标对象</p>\n<p>• <code>swap(string other)</code> 与 other 交换内容</p>\n<p>例:</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">/* str-method-substr.cpp */</span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span><span class=\"string\"><iostream></span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span><span class=\"string\"><string></span></span></span><br><span class=\"line\"><span class=\"keyword\">using</span> <span class=\"keyword\">namespace</span> std;</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span><span class=\"params\">()</span> </span>{</span><br><span class=\"line\">string s = <span class=\"string\">"Sysu-Computer"</span>;</span><br><span class=\"line\">cout << s.<span class=\"built_in\">substr</span>(<span class=\"number\">0</span>,<span class=\"number\">4</span>) << <span class=\"string\">" "</span>;</span><br><span class=\"line\"><span class=\"keyword\">if</span> (s.<span class=\"built_in\">compare</span>(<span class=\"number\">5</span>,<span class=\"number\">8</span>,<span class=\"string\">"Computer"</span>)==<span class=\"number\">0</span>) {</span><br><span class=\"line\">cout << <span class=\"string\">"OK!"</span> << endl;</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"keyword\">return</span> <span class=\"number\">0</span>;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span> <span class=\"string\"><iostream></span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span> <span class=\"string\"><algorithm></span></span></span><br><span class=\"line\"><span class=\"keyword\">using</span> <span class=\"keyword\">namespace</span> std;</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span><span class=\"params\">()</span> </span>{</span><br><span class=\"line\"> <span class=\"type\">int</span> a = <span class=\"number\">5</span>, b = <span class=\"number\">10</span>;</span><br><span class=\"line\"> cout << <span class=\"string\">"交换前:a="</span> << a << <span class=\"string\">", b="</span> << b << endl;</span><br><span class=\"line\"> <span class=\"built_in\">swap</span>(a, b); <span class=\"comment\">// 直接调用标准库的swap函数</span></span><br><span class=\"line\"> cout << <span class=\"string\">"交换后:a="</span> << a << <span class=\"string\">", b="</span> << b << endl;</span><br><span class=\"line\"> <span class=\"keyword\">return</span> <span class=\"number\">0</span>;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<h2 id=\"使用-C-标准库\"><a href=\"#使用-C-标准库\" class=\"headerlink\" title=\"使用 C 标准库\"></a>使用 C 标准库</h2><p>C 标准库,即不仅可以用 g++ 编译 c 风格的 cpp 程序,也可以使用 C 库函数</p>\n<h2 id=\"const-constexpr\"><a href=\"#const-constexpr\" class=\"headerlink\" title=\"const & constexpr\"></a>const & constexpr</h2><p>const :<br>• 限定为不可修改(只读)变量<br>• 限定作为常量或字面量</p>\n<p>constexpr :<br>声明编译时可以对函数或变量求值。<br>• 限定为常量表达式<br>• 限定为编译时可优化执行的函数</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"function\"><span class=\"keyword\">constexpr</span> <span class=\"type\">int</span> <span class=\"title\">d</span><span class=\"params\">()</span> </span>{ <span class=\"keyword\">return</span> <span class=\"number\">40</span>; }</span><br></pre></td></tr></table></figure>\n\n<p>constexpr 函数允许返回编译期常量。此处返回 40 是合法的常量表达式,且函数体符合 constexpr 的语法要求</p>\n<p><strong>即凡是表达“只读”语义的场景都使用 const,表达“常量”语义的场景都使用 constexpr</strong></p>\n<h2 id=\"auto,bool-关键字\"><a href=\"#auto,bool-关键字\" class=\"headerlink\" title=\"auto,bool 关键字\"></a>auto,bool 关键字</h2><h3 id=\"auto\"><a href=\"#auto\" class=\"headerlink\" title=\"auto\"></a>auto</h3><p>auto 的原理就是根据初始化的表达式,在编译期间根据表达式类型自动推<br>导出对象的类型。</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">auto</span> x1 = <span class=\"number\">5</span>; 等价于 <span class=\"type\">int</span> x1 = <span class=\"number\">5</span>;</span><br></pre></td></tr></table></figure>\n\n<p>注意点: 1.用 auto 声明的变量必须初始化 2.函数和模板参数不能被声明为 auto 3.因为 auto 是一个占位符,并不是一个他自己的类型,因此不能用于类型转换或其<br>他一些操作,如 sizeof 和 typeid 4.定义在一个 auto 序列的变量必须始终推导成同一类型</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">auto</span> x1 = <span class=\"number\">5</span>,x2 = <span class=\"number\">5.0</span>,x3=<span class=\"string\">'r'</span>; <span class=\"comment\">//这样写是不合法的,因为各个变量类型不同</span></span><br></pre></td></tr></table></figure>\n\n<h3 id=\"bool\"><a href=\"#bool\" class=\"headerlink\" title=\"bool\"></a>bool</h3><p>bool - 是存放两个值 true 或 false 之一的类型。</p>\n<h4 id=\"初始化\"><a href=\"#初始化\" class=\"headerlink\" title=\"初始化\"></a>初始化</h4><figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"type\">bool</span> flag = <span class=\"literal\">false</span>;</span><br><span class=\"line\"><span class=\"type\">bool</span> flag = <span class=\"number\">1</span>;</span><br></pre></td></tr></table></figure>\n\n<h4 id=\"隐式转换规则-\"><a href=\"#隐式转换规则-\" class=\"headerlink\" title=\"隐式转换规则 \"></a>隐式转换规则 </h4><p>任何非零的整型值(无论是正数还是负数)在转换为布尔型时都会变为 true,而零值会转换为 false。因此,-5 作为非零整数,赋值给布尔变量时会得到 true</p>\n<h1 id=\"理论题\"><a href=\"#理论题\" class=\"headerlink\" title=\"理论题\"></a>理论题</h1><h2 id=\"typeid-操作符\"><a href=\"#typeid-操作符\" class=\"headerlink\" title=\"typeid 操作符\"></a>typeid 操作符</h2><h3 id=\"1--获取类型信息\"><a href=\"#1--获取类型信息\" class=\"headerlink\" title=\"1. 获取类型信息\"></a>1. 获取类型信息</h3><figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"type\">float</span> f = <span class=\"number\">1.1f</span>;</span><br><span class=\"line\">std::cout << <span class=\"built_in\">typeid</span>(f).<span class=\"built_in\">name</span>(); <span class=\"comment\">// 可能输出"float"(依赖编译器实现)</span></span><br></pre></td></tr></table></figure>\n\n<h3 id=\"2-类型检查与比较\"><a href=\"#2-类型检查与比较\" class=\"headerlink\" title=\"2.类型检查与比较\"></a>2.类型检查与比较</h3><figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\">Base* ptr = <span class=\"keyword\">new</span> <span class=\"built_in\">Derived</span>();</span><br><span class=\"line\"><span class=\"keyword\">if</span> (<span class=\"built_in\">typeid</span>(*ptr) == <span class=\"built_in\">typeid</span>(Derived)) { <span class=\"comment\">// 若Base是多态类(含虚函数)</span></span><br><span class=\"line\"><span class=\"comment\">// 执行派生类相关逻辑</span></span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<h2 id=\"empty-函数\"><a href=\"#empty-函数\" class=\"headerlink\" title=\"empty 函数\"></a>empty 函数</h2><p>判断字符串是否为空的成员函数</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\">std::string s = <span class=\"string\">""</span>;</span><br><span class=\"line\"><span class=\"keyword\">if</span> (s.<span class=\"built_in\">empty</span>()) {</span><br><span class=\"line\"> std::cout << <span class=\"string\">"字符串为空"</span>;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<h2 id=\"find\"><a href=\"#find\" class=\"headerlink\" title=\"find\"></a>find</h2><p>当 find()方法找不到子串时返回:**<code>string::npos</code>**</p>\n<p>string::find()的返回值类型是 size_type(无符号整型),而非简单的 intbool。当查找失败时,它不会返回-1 或 false,而是返回一个特殊常量 string::npos</p>\n<h2 id=\"范围-for-循环\"><a href=\"#范围-for-循环\" class=\"headerlink\" title=\"范围 for 循环\"></a>范围 for 循环</h2><p>范围 for 循环遍历字符串 str 中每个字符</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">for</span>(<span class=\"type\">char</span> c : str) {</span><br><span class=\"line\"> cout << c; }</span><br></pre></td></tr></table></figure>\n\n<h2 id=\"双引号-“-“-与-单引号-‘-‘\"><a href=\"#双引号-“-“-与-单引号-‘-‘\" class=\"headerlink\" title=\"双引号 “ “ 与 单引号 ‘ ‘\"></a>双引号 “ “ 与 单引号 ‘ ‘</h2><h3 id=\"双引号-“”\"><a href=\"#双引号-“”\" class=\"headerlink\" title=\"双引号 “”\"></a>双引号 “”</h3><p>双引号 “”:字符串字面量(String Literal)<br>用途:表示一个字符串(多个字符组成的序列)。</p>\n<p>类型:<code>const char\\*(C 风格字符串)或隐式转换为 std::string</code></p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"type\">const</span> <span class=\"type\">char</span>* s1 = <span class=\"string\">"Hello"</span>; <span class=\"comment\">// C风格字符串</span></span><br><span class=\"line\">std::string s2 = <span class=\"string\">"World"</span>; <span class=\"comment\">// C++字符串对象</span></span><br></pre></td></tr></table></figure>\n\n<h3 id=\"单引号-‘’\"><a href=\"#单引号-‘’\" class=\"headerlink\" title=\"单引号 ‘’\"></a>单引号 ‘’</h3><p>单引号 ‘’:字符字面量(Character Literal)<br>用途:表示一个单个字符。</p>\n<p>类型:<code>char。</code><br>[========]</p>\n<p>[========]</p>\n<p>内存表示:仅存储单个字符的 ASCII 值。</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"type\">char</span> c1 = <span class=\"string\">'A'</span>; <span class=\"comment\">// 正确</span></span><br><span class=\"line\"><span class=\"type\">char</span> c2 = <span class=\"string\">'\\n'</span>; <span class=\"comment\">// 正确(转义字符)</span></span><br><span class=\"line\"><span class=\"comment\">// char c3 = 'AB'; // 错误:单引号内只能有一个字符</span></span><br></pre></td></tr></table></figure>\n\n<p>注:<strong>混淆二者会导致编译错误或逻辑错误。</strong></p>\n<p>错误 1:单引号包裹多个字符</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"type\">char</span> c = <span class=\"string\">'AB'</span>; <span class=\"comment\">// 编译错误!单引号内只能有一个字符</span></span><br></pre></td></tr></table></figure>\n\n<p>错误 2:混淆字符和字符串比较</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\">std::string s = <span class=\"string\">"A"</span>;</span><br><span class=\"line\"><span class=\"keyword\">if</span> (s == <span class=\"string\">'A'</span>) { <span class=\"comment\">// 错误!'A'是char,s是std::string</span></span><br><span class=\"line\"> <span class=\"comment\">// ...</span></span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"comment\">// 正确写法:if (s == "A") 或 if (s[0] == 'A')</span></span><br></pre></td></tr></table></figure>\n\n<p>错误 3:误用双引号初始化 char</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"type\">char</span> c = <span class=\"string\">"A"</span>; <span class=\"comment\">// 错误!"A"是const char*,无法赋值给char</span></span><br><span class=\"line\"><span class=\"comment\">// 正确写法:char c = 'A';</span></span><br></pre></td></tr></table></figure>\n\n<h2 id=\"vector-容器\"><a href=\"#vector-容器\" class=\"headerlink\" title=\"vector 容器\"></a>vector 容器</h2><p>等待填坑</p>\n","excerpt":"","more":"<h1 id=\"初学-C\"><a href=\"#初学-C\" class=\"headerlink\" title=\"初学 C++\"></a>初学 C++</h1><hr>\n<h2 id=\"string-类与操作\"><a href=\"#string-类与操作\" class=\"headerlink\" title=\"string 类与操作\"></a>string 类与操作</h2><h3 id=\"初识类\"><a href=\"#初识类\" class=\"headerlink\" title=\"初识类\"></a>初识类</h3><p><strong>类是现实世界或抽象世界中概念,是关于同类事物定义的描述</strong></p>\n<p>在标准库中有很多类,通过以下类可体验与 C 语言的不同<br>• < string >库中的<code>std::string</code> 类<br>• 输入/输出库中的 <code>std::ifstream, std::ofstream</code> 类</p>\n<h3 id=\"string-类-与-C-风格字符串\"><a href=\"#string-类-与-C-风格字符串\" class=\"headerlink\" title=\"string 类 与 C 风格字符串\"></a>string 类 与 C 风格字符串</h3><p>C 风格字符串的缺点:</p>\n<p>1.C 风格字符串是使用 null 字符 ‘\\0’ 终止的一维字符数组。因而字符串定义时,必须事先知道保留多大空间存储字符串</p>\n<p>2.在字符串操作,如 strcat,时要保证目标字符串有足够的空间</p>\n<p>3.使用 malloc 动态空间处理字符串,对一般程序员来说太复杂,非常容易出现<br>BUG</p>\n<h3 id=\"创建-string\"><a href=\"#创建-string\" class=\"headerlink\" title=\"创建 string\"></a>创建 string</h3><figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\">string s1;</span><br><span class=\"line\">string s2 = <span class=\"string\">"c++"</span>;</span><br><span class=\"line\">string s3 = s2;</span><br><span class=\"line\"><span class=\"function\">string <span class=\"title\">s4</span> <span class=\"params\">(<span class=\"number\">5</span>, <span class=\"string\">'s'</span>)</span></span>;<span class=\"comment\">//s4 初始化为 5 个 s</span></span><br></pre></td></tr></table></figure>\n\n<h3 id=\"string-对象的运算\"><a href=\"#string-对象的运算\" class=\"headerlink\" title=\"string 对象的运算\"></a>string 对象的运算</h3><p><code>string</code> 类实现了以下运算符的重载</p>\n<p>1.联接运算:<code>operator+</code>,连接两个字符串或者一个字符串和一个字符</p>\n<p>2.比较运算:<code>operator,<,<=,>,>=,<=></code>(c++20 起),以字典序比较两个字符串(关系运算符)</p>\n<p>3.下标运算:<code>operator[]</code>,访问指定字符,返回指定字符引用,即可作为左值</p>\n<p>4.赋值运算:<code>operator=,+=</code>,右操作数可以是字符串,字符,C 字符串,字符数组</p>\n<p>ps:字符串比较运算符<code>==,!=</code>的作用是:逐字符比较两个字符串内容</p>\n<h3 id=\"string-对象的操作\"><a href=\"#string-对象的操作\" class=\"headerlink\" title=\"string 对象的操作\"></a>string 对象的操作</h3><h4 id=\"函数重载\"><a href=\"#函数重载\" class=\"headerlink\" title=\"函数重载\"></a>函数重载</h4><p>C++ 则允许多个函数拥有相同的名字,只要它们的参数列表不同就可以,这就是函数的重载</p>\n<figure class=\"highlight routeros\"><table><tr><td class=\"code\"><pre><span class=\"line\">以 string 对象的 <span class=\"built_in\">find</span> 函数为例:</span><br><span class=\"line\">• s.<span class=\"built_in\">find</span>(str) 在 s 中查找子串 str</span><br><span class=\"line\">• s.<span class=\"built_in\">find</span>(<span class=\"string\">"hello"</span>,3) 在s中从第4个位置开始查找子串<span class=\"string\">"hello"</span></span><br><span class=\"line\">• s.<span class=\"built_in\">find</span>(<span class=\"string\">'H'</span>)在 s 中查找字符<span class=\"string\">'H'</span></span><br></pre></td></tr></table></figure>\n\n<h4 id=\"基本操作\"><a href=\"#基本操作\" class=\"headerlink\" title=\"基本操作\"></a>基本操作</h4><p><strong><code>length()</code> 返回类型 <code>size_t</code> 的字符串的长度</strong></p>\n<p><strong><code>c_str()</code> 返回类型 <code>const char \\*</code> 的 C 风格字符串。以 null 结束</strong><br>例:</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">/* str-method-basic.cpp */</span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span><span class=\"string\"><iostream></span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span><span class=\"string\"><string></span></span></span><br><span class=\"line\"><span class=\"keyword\">using</span> <span class=\"keyword\">namespace</span> std;</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span><span class=\"params\">()</span> </span>{</span><br><span class=\"line\">string s = <span class=\"string\">"sysu-computer"</span>;</span><br><span class=\"line\"><span class=\"type\">int</span> len = s.<span class=\"built_in\">length</span>();</span><br><span class=\"line\"><span class=\"type\">const</span> <span class=\"type\">char</span>* cs = s.<span class=\"built_in\">c_str</span>();</span><br><span class=\"line\">cout << cs << <span class=\"string\">" len is "</span></span><br><span class=\"line\"><< len << endl;</span><br><span class=\"line\"><span class=\"keyword\">return</span> <span class=\"number\">0</span>;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<h4 id=\"查找、替换\"><a href=\"#查找、替换\" class=\"headerlink\" title=\"查找、替换\"></a>查找、替换</h4><p><strong><code>find(string|char\\*|char s [,int pos=0])</code> 寻找首个等于给定字符序列的子串。搜索始于 pos,返回类型 size_t 的位置。rfind 从右边开始搜索</strong></p>\n<p><strong><code>replace(int pos, int count, string|char\\*|char s)</code> 替换指定范围内容</strong><br>例:</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">/* str-method-find.cpp */</span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span><span class=\"string\"><iostream></span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span><span class=\"string\"><string></span></span></span><br><span class=\"line\"><span class=\"keyword\">using</span> <span class=\"keyword\">namespace</span> std;</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span><span class=\"params\">()</span> </span>{</span><br><span class=\"line\">string s = <span class=\"string\">"sysu-computer"</span>;</span><br><span class=\"line\"><span class=\"type\">int</span> pos = s.<span class=\"built_in\">find</span>(<span class=\"string\">"computer"</span>);</span><br><span class=\"line\">s.<span class=\"built_in\">replace</span>(pos,<span class=\"number\">8</span>,<span class=\"string\">"software"</span>);</span><br><span class=\"line\">cout << s << endl;</span><br><span class=\"line\"><span class=\"keyword\">return</span> <span class=\"number\">0</span>;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<h4 id=\"添加,插入,删除\"><a href=\"#添加,插入,删除\" class=\"headerlink\" title=\"添加,插入,删除\"></a>添加,插入,删除</h4><p><code>append(string)</code> 后附 string str</p>\n<p><code>append(int count, char ch)</code> 后 附 count 个字符 ch</p>\n<p><code>insert(int index, int count, char ch)</code> 在 index 位置插入 count 个 ch</p>\n<p><code>insert(int index, string|char\\* s)</code> 在 index 位置插入 s</p>\n<p><code>erase(int index, int count)</code> 删 除 从 index 开始的 count 个字符</p>\n<p><code>clear()</code> 清空<br>注:clear() 仅清空字符串中的有效字符(即 size() 变为 0),但不会释放已分配的内存空间。这意味着 capacity()(预分配的内存容量)不会改变</p>\n<p>例:</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">/* str-method-insert.cpp */</span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span><span class=\"string\"><iostream></span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span><span class=\"string\"><string></span></span></span><br><span class=\"line\"><span class=\"keyword\">using</span> <span class=\"keyword\">namespace</span> std;</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span><span class=\"params\">()</span> </span>{</span><br><span class=\"line\">string s = <span class=\"string\">"ysu"</span>;</span><br><span class=\"line\">s.<span class=\"built_in\">insert</span>(<span class=\"number\">0</span>,<span class=\"number\">1</span>,<span class=\"string\">'S'</span>).<span class=\"built_in\">append</span>(<span class=\"number\">1</span>,<span class=\"string\">'-'</span>).<span class=\"built_in\">append</span>(<span class=\"string\">"Xcomputer"</span>);</span><br><span class=\"line\">s.<span class=\"built_in\">erase</span>(<span class=\"number\">5</span>,<span class=\"number\">1</span>);</span><br><span class=\"line\">cout << s << endl;</span><br><span class=\"line\"><span class=\"keyword\">return</span> <span class=\"number\">0</span>;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<h4 id=\"子串、比较、拷贝、交换\"><a href=\"#子串、比较、拷贝、交换\" class=\"headerlink\" title=\"子串、比较、拷贝、交换\"></a>子串、比较、拷贝、交换</h4><p>• <code>substr(int pos, int count)</code> 返回子串对<br>象</p>\n<p>• <code>compare(string|char\\* str)</code> 与 str 比较,<br>返回 1,0,-1 之一</p>\n<p>• <code>compare(int pos, int count</code>,<br>string|char* str) 字串与 str 比较,返回<br>1,0,-1 之一<br>compare 用于比较两个字符串的字典序关系</p>\n<p>• <code>copy(string|char\\* dest, int pos, int count)</code> 将子串复制到目标对象</p>\n<p>• <code>swap(string other)</code> 与 other 交换内容</p>\n<p>例:</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">/* str-method-substr.cpp */</span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span><span class=\"string\"><iostream></span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span><span class=\"string\"><string></span></span></span><br><span class=\"line\"><span class=\"keyword\">using</span> <span class=\"keyword\">namespace</span> std;</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span><span class=\"params\">()</span> </span>{</span><br><span class=\"line\">string s = <span class=\"string\">"Sysu-Computer"</span>;</span><br><span class=\"line\">cout << s.<span class=\"built_in\">substr</span>(<span class=\"number\">0</span>,<span class=\"number\">4</span>) << <span class=\"string\">" "</span>;</span><br><span class=\"line\"><span class=\"keyword\">if</span> (s.<span class=\"built_in\">compare</span>(<span class=\"number\">5</span>,<span class=\"number\">8</span>,<span class=\"string\">"Computer"</span>)==<span class=\"number\">0</span>) {</span><br><span class=\"line\">cout << <span class=\"string\">"OK!"</span> << endl;</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"keyword\">return</span> <span class=\"number\">0</span>;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span> <span class=\"string\"><iostream></span></span></span><br><span class=\"line\"><span class=\"meta\">#<span class=\"keyword\">include</span> <span class=\"string\"><algorithm></span></span></span><br><span class=\"line\"><span class=\"keyword\">using</span> <span class=\"keyword\">namespace</span> std;</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span><span class=\"params\">()</span> </span>{</span><br><span class=\"line\"> <span class=\"type\">int</span> a = <span class=\"number\">5</span>, b = <span class=\"number\">10</span>;</span><br><span class=\"line\"> cout << <span class=\"string\">"交换前:a="</span> << a << <span class=\"string\">", b="</span> << b << endl;</span><br><span class=\"line\"> <span class=\"built_in\">swap</span>(a, b); <span class=\"comment\">// 直接调用标准库的swap函数</span></span><br><span class=\"line\"> cout << <span class=\"string\">"交换后:a="</span> << a << <span class=\"string\">", b="</span> << b << endl;</span><br><span class=\"line\"> <span class=\"keyword\">return</span> <span class=\"number\">0</span>;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<h2 id=\"使用-C-标准库\"><a href=\"#使用-C-标准库\" class=\"headerlink\" title=\"使用 C 标准库\"></a>使用 C 标准库</h2><p>C 标准库,即不仅可以用 g++ 编译 c 风格的 cpp 程序,也可以使用 C 库函数</p>\n<h2 id=\"const-constexpr\"><a href=\"#const-constexpr\" class=\"headerlink\" title=\"const & constexpr\"></a>const & constexpr</h2><p>const :<br>• 限定为不可修改(只读)变量<br>• 限定作为常量或字面量</p>\n<p>constexpr :<br>声明编译时可以对函数或变量求值。<br>• 限定为常量表达式<br>• 限定为编译时可优化执行的函数</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"function\"><span class=\"keyword\">constexpr</span> <span class=\"type\">int</span> <span class=\"title\">d</span><span class=\"params\">()</span> </span>{ <span class=\"keyword\">return</span> <span class=\"number\">40</span>; }</span><br></pre></td></tr></table></figure>\n\n<p>constexpr 函数允许返回编译期常量。此处返回 40 是合法的常量表达式,且函数体符合 constexpr 的语法要求</p>\n<p><strong>即凡是表达“只读”语义的场景都使用 const,表达“常量”语义的场景都使用 constexpr</strong></p>\n<h2 id=\"auto,bool-关键字\"><a href=\"#auto,bool-关键字\" class=\"headerlink\" title=\"auto,bool 关键字\"></a>auto,bool 关键字</h2><h3 id=\"auto\"><a href=\"#auto\" class=\"headerlink\" title=\"auto\"></a>auto</h3><p>auto 的原理就是根据初始化的表达式,在编译期间根据表达式类型自动推<br>导出对象的类型。</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">auto</span> x1 = <span class=\"number\">5</span>; 等价于 <span class=\"type\">int</span> x1 = <span class=\"number\">5</span>;</span><br></pre></td></tr></table></figure>\n\n<p>注意点: 1.用 auto 声明的变量必须初始化 2.函数和模板参数不能被声明为 auto 3.因为 auto 是一个占位符,并不是一个他自己的类型,因此不能用于类型转换或其<br>他一些操作,如 sizeof 和 typeid 4.定义在一个 auto 序列的变量必须始终推导成同一类型</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">auto</span> x1 = <span class=\"number\">5</span>,x2 = <span class=\"number\">5.0</span>,x3=<span class=\"string\">'r'</span>; <span class=\"comment\">//这样写是不合法的,因为各个变量类型不同</span></span><br></pre></td></tr></table></figure>\n\n<h3 id=\"bool\"><a href=\"#bool\" class=\"headerlink\" title=\"bool\"></a>bool</h3><p>bool - 是存放两个值 true 或 false 之一的类型。</p>\n<h4 id=\"初始化\"><a href=\"#初始化\" class=\"headerlink\" title=\"初始化\"></a>初始化</h4><figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"type\">bool</span> flag = <span class=\"literal\">false</span>;</span><br><span class=\"line\"><span class=\"type\">bool</span> flag = <span class=\"number\">1</span>;</span><br></pre></td></tr></table></figure>\n\n<h4 id=\"隐式转换规则-\"><a href=\"#隐式转换规则-\" class=\"headerlink\" title=\"隐式转换规则 \"></a>隐式转换规则 </h4><p>任何非零的整型值(无论是正数还是负数)在转换为布尔型时都会变为 true,而零值会转换为 false。因此,-5 作为非零整数,赋值给布尔变量时会得到 true</p>\n<h1 id=\"理论题\"><a href=\"#理论题\" class=\"headerlink\" title=\"理论题\"></a>理论题</h1><h2 id=\"typeid-操作符\"><a href=\"#typeid-操作符\" class=\"headerlink\" title=\"typeid 操作符\"></a>typeid 操作符</h2><h3 id=\"1--获取类型信息\"><a href=\"#1--获取类型信息\" class=\"headerlink\" title=\"1. 获取类型信息\"></a>1. 获取类型信息</h3><figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"type\">float</span> f = <span class=\"number\">1.1f</span>;</span><br><span class=\"line\">std::cout << <span class=\"built_in\">typeid</span>(f).<span class=\"built_in\">name</span>(); <span class=\"comment\">// 可能输出"float"(依赖编译器实现)</span></span><br></pre></td></tr></table></figure>\n\n<h3 id=\"2-类型检查与比较\"><a href=\"#2-类型检查与比较\" class=\"headerlink\" title=\"2.类型检查与比较\"></a>2.类型检查与比较</h3><figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\">Base* ptr = <span class=\"keyword\">new</span> <span class=\"built_in\">Derived</span>();</span><br><span class=\"line\"><span class=\"keyword\">if</span> (<span class=\"built_in\">typeid</span>(*ptr) == <span class=\"built_in\">typeid</span>(Derived)) { <span class=\"comment\">// 若Base是多态类(含虚函数)</span></span><br><span class=\"line\"><span class=\"comment\">// 执行派生类相关逻辑</span></span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<h2 id=\"empty-函数\"><a href=\"#empty-函数\" class=\"headerlink\" title=\"empty 函数\"></a>empty 函数</h2><p>判断字符串是否为空的成员函数</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\">std::string s = <span class=\"string\">""</span>;</span><br><span class=\"line\"><span class=\"keyword\">if</span> (s.<span class=\"built_in\">empty</span>()) {</span><br><span class=\"line\"> std::cout << <span class=\"string\">"字符串为空"</span>;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<h2 id=\"find\"><a href=\"#find\" class=\"headerlink\" title=\"find\"></a>find</h2><p>当 find()方法找不到子串时返回:**<code>string::npos</code>**</p>\n<p>string::find()的返回值类型是 size_type(无符号整型),而非简单的 intbool。当查找失败时,它不会返回-1 或 false,而是返回一个特殊常量 string::npos</p>\n<h2 id=\"范围-for-循环\"><a href=\"#范围-for-循环\" class=\"headerlink\" title=\"范围 for 循环\"></a>范围 for 循环</h2><p>范围 for 循环遍历字符串 str 中每个字符</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">for</span>(<span class=\"type\">char</span> c : str) {</span><br><span class=\"line\"> cout << c; }</span><br></pre></td></tr></table></figure>\n\n<h2 id=\"双引号-“-“-与-单引号-‘-‘\"><a href=\"#双引号-“-“-与-单引号-‘-‘\" class=\"headerlink\" title=\"双引号 “ “ 与 单引号 ‘ ‘\"></a>双引号 “ “ 与 单引号 ‘ ‘</h2><h3 id=\"双引号-“”\"><a href=\"#双引号-“”\" class=\"headerlink\" title=\"双引号 “”\"></a>双引号 “”</h3><p>双引号 “”:字符串字面量(String Literal)<br>用途:表示一个字符串(多个字符组成的序列)。</p>\n<p>类型:<code>const char\\*(C 风格字符串)或隐式转换为 std::string</code></p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"type\">const</span> <span class=\"type\">char</span>* s1 = <span class=\"string\">"Hello"</span>; <span class=\"comment\">// C风格字符串</span></span><br><span class=\"line\">std::string s2 = <span class=\"string\">"World"</span>; <span class=\"comment\">// C++字符串对象</span></span><br></pre></td></tr></table></figure>\n\n<h3 id=\"单引号-‘’\"><a href=\"#单引号-‘’\" class=\"headerlink\" title=\"单引号 ‘’\"></a>单引号 ‘’</h3><p>单引号 ‘’:字符字面量(Character Literal)<br>用途:表示一个单个字符。</p>\n<p>类型:<code>char。</code><br>[========]</p>\n<p>[========]</p>\n<p>内存表示:仅存储单个字符的 ASCII 值。</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"type\">char</span> c1 = <span class=\"string\">'A'</span>; <span class=\"comment\">// 正确</span></span><br><span class=\"line\"><span class=\"type\">char</span> c2 = <span class=\"string\">'\\n'</span>; <span class=\"comment\">// 正确(转义字符)</span></span><br><span class=\"line\"><span class=\"comment\">// char c3 = 'AB'; // 错误:单引号内只能有一个字符</span></span><br></pre></td></tr></table></figure>\n\n<p>注:<strong>混淆二者会导致编译错误或逻辑错误。</strong></p>\n<p>错误 1:单引号包裹多个字符</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"type\">char</span> c = <span class=\"string\">'AB'</span>; <span class=\"comment\">// 编译错误!单引号内只能有一个字符</span></span><br></pre></td></tr></table></figure>\n\n<p>错误 2:混淆字符和字符串比较</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\">std::string s = <span class=\"string\">"A"</span>;</span><br><span class=\"line\"><span class=\"keyword\">if</span> (s == <span class=\"string\">'A'</span>) { <span class=\"comment\">// 错误!'A'是char,s是std::string</span></span><br><span class=\"line\"> <span class=\"comment\">// ...</span></span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"comment\">// 正确写法:if (s == "A") 或 if (s[0] == 'A')</span></span><br></pre></td></tr></table></figure>\n\n<p>错误 3:误用双引号初始化 char</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"type\">char</span> c = <span class=\"string\">"A"</span>; <span class=\"comment\">// 错误!"A"是const char*,无法赋值给char</span></span><br><span class=\"line\"><span class=\"comment\">// 正确写法:char c = 'A';</span></span><br></pre></td></tr></table></figure>\n\n<h2 id=\"vector-容器\"><a href=\"#vector-容器\" class=\"headerlink\" title=\"vector 容器\"></a>vector 容器</h2><p>等待填坑</p>\n"},{"title":"用于测试","top_img":"transparent","comments":0,"_content":"\n测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试\n","source":"_posts/test.md","raw":"---\ntitle: 用于测试\ntags: C++\ntop_img: transparent\ncomments: false\n---\n\n测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试\n","slug":"test","published":1,"date":"2026-01-20T08:25:00.348Z","updated":"2026-01-20T08:25:39.482Z","layout":"post","photos":[],"_id":"cmkmd8tz0000mcw64f3t5fxrq","content":"<link rel=\"stylesheet\" class=\"aplayer-secondary-style-marker\" href=\"\\assets\\css\\APlayer.min.css\"><script src=\"\\assets\\js\\APlayer.min.js\" class=\"aplayer-secondary-script-marker\"></script><p>测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试</p>\n","excerpt":"","more":"<p>测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试</p>\n"},{"_content":" 整数转字符 :\n数字 + '0' 的正确场景 :仅适用于 单个数字(0-9) 转字符\na % 4 的结果是一个 0 到 3 的整数。\n'0' 的 ASCII 码是 48,所以:\n0 + '0' = 48 → '0'\n1 + '0' = 49 → '1'\n2 + '0' = 50 → '2'\n3 + '0' = 51 → '3'\n这样就将整数 0-3 转换为对应的字符'0'到'3'。\n 字符转整数 :\n反过来,字符'0'到'3'减去'0':\n'0' - '0' = 0\n'1' - '0' = 1\n'2' - '0' = 2\n'3' - '0' = 3\n这样就将字符'0'到'3'转换为对应的整数 0-3。\n\n关键点总结\n操作 作用 示例\nint + '0' 将整数 0-9 转换为对应字符 2 + '0' → '2'\nchar - '0' 将字符'0'-'9'转换为对应整数 '2' - '0' → 2\nstd::to_string() 直接转换任意类型为字符串 std::to_string(42) → \"42\"\n\n运算符重载的主要目的是 让运算符适用于自定义类型 (类或结构体)\n\n运算符重载必须至少有一个操作数是用户定义类型 \n","source":"_posts/sixth-blog.md","raw":" 整数转字符 :\n数字 + '0' 的正确场景 :仅适用于 单个数字(0-9) 转字符\na % 4 的结果是一个 0 到 3 的整数。\n'0' 的 ASCII 码是 48,所以:\n0 + '0' = 48 → '0'\n1 + '0' = 49 → '1'\n2 + '0' = 50 → '2'\n3 + '0' = 51 → '3'\n这样就将整数 0-3 转换为对应的字符'0'到'3'。\n 字符转整数 :\n反过来,字符'0'到'3'减去'0':\n'0' - '0' = 0\n'1' - '0' = 1\n'2' - '0' = 2\n'3' - '0' = 3\n这样就将字符'0'到'3'转换为对应的整数 0-3。\n\n关键点总结\n操作 作用 示例\nint + '0' 将整数 0-9 转换为对应字符 2 + '0' → '2'\nchar - '0' 将字符'0'-'9'转换为对应整数 '2' - '0' → 2\nstd::to_string() 直接转换任意类型为字符串 std::to_string(42) → \"42\"\n\n运算符重载的主要目的是 让运算符适用于自定义类型 (类或结构体)\n\n运算符重载必须至少有一个操作数是用户定义类型 \n","slug":"sixth-blog","published":1,"date":"2025-04-08T08:57:37.067Z","updated":"2025-04-09T13:33:00.371Z","title":"","comments":1,"layout":"post","photos":[],"_id":"cmkmd8tz0000ocw64e0l59pef","content":"<link rel=\"stylesheet\" class=\"aplayer-secondary-style-marker\" href=\"\\assets\\css\\APlayer.min.css\"><script src=\"\\assets\\js\\APlayer.min.js\" class=\"aplayer-secondary-script-marker\"></script><p> 整数转字符 :<br>数字 + ‘0’ 的正确场景 :仅适用于 单个数字(0-9) 转字符<br>a % 4 的结果是一个 0 到 3 的整数。<br>‘0’ 的 ASCII 码是 48,所以:<br>0 + ‘0’ = 48 → ‘0’<br>1 + ‘0’ = 49 → ‘1’<br>2 + ‘0’ = 50 → ‘2’<br>3 + ‘0’ = 51 → ‘3’<br>这样就将整数 0-3 转换为对应的字符’0’到’3’。<br> 字符转整数 :<br>反过来,字符’0’到’3’减去’0’:<br>‘0’ - ‘0’ = 0<br>‘1’ - ‘0’ = 1<br>‘2’ - ‘0’ = 2<br>‘3’ - ‘0’ = 3<br>这样就将字符’0’到’3’转换为对应的整数 0-3。</p>\n<p>关键点总结<br>操作 作用 示例<br>int + ‘0’ 将整数 0-9 转换为对应字符 2 + ‘0’ → ‘2’<br>char - ‘0’ 将字符’0’-‘9’转换为对应整数 ‘2’ - ‘0’ → 2<br>std::to_string() 直接转换任意类型为字符串 std::to_string(42) → “42”</p>\n<p>运算符重载的主要目的是 让运算符适用于自定义类型 (类或结构体)</p>\n<p>运算符重载必须至少有一个操作数是用户定义类型 </p>\n","excerpt":"","more":"<p> 整数转字符 :<br>数字 + ‘0’ 的正确场景 :仅适用于 单个数字(0-9) 转字符<br>a % 4 的结果是一个 0 到 3 的整数。<br>‘0’ 的 ASCII 码是 48,所以:<br>0 + ‘0’ = 48 → ‘0’<br>1 + ‘0’ = 49 → ‘1’<br>2 + ‘0’ = 50 → ‘2’<br>3 + ‘0’ = 51 → ‘3’<br>这样就将整数 0-3 转换为对应的字符’0’到’3’。<br> 字符转整数 :<br>反过来,字符’0’到’3’减去’0’:<br>‘0’ - ‘0’ = 0<br>‘1’ - ‘0’ = 1<br>‘2’ - ‘0’ = 2<br>‘3’ - ‘0’ = 3<br>这样就将字符’0’到’3’转换为对应的整数 0-3。</p>\n<p>关键点总结<br>操作 作用 示例<br>int + ‘0’ 将整数 0-9 转换为对应字符 2 + ‘0’ → ‘2’<br>char - ‘0’ 将字符’0’-‘9’转换为对应整数 ‘2’ - ‘0’ → 2<br>std::to_string() 直接转换任意类型为字符串 std::to_string(42) → “42”</p>\n<p>运算符重载的主要目的是 让运算符适用于自定义类型 (类或结构体)</p>\n<p>运算符重载必须至少有一个操作数是用户定义类型 </p>\n"},{"title":"数据抽象与类","top_img":"transparent","comments":0,"_content":"\n# 数据抽象与类\n\n## 抽象数据类型\n\n1.抽象是从众多的事物中抽取出共同的、本质性的特征,而舍弃其非本质的特征的过程。\n\n2.抽象的过程在于透过事物的现象获得它的本质,并用概念、原理、规律的形式描述它。\n\n3.抽象的意义在于通过事物的本质,识别或区分事物\n\n## 类的声明\n\n### 类关键词\n\n**class 或 struct 或 union **\n用 class 定义的类,默认访问权限为`private`\n用 struct 定义的结构体,默认访问权限为`public`\n\n### 访问说明符\n\n• `public` 公有,表示后续成员是对象使用者可访问\n\n• `private` 私有,表示后续成员仅对象内部可访问\n\n• `protected` 受保护\n\n### 类成员\n\n• 数据成员,按声明顺序存储,对齐规则同 C。\n一般设计中,数据成员需要隐藏保护,需要通过函数成员访问\n\n• 函数成员,公有成员可以被外部使用者访问;\n私有成员仅内部访问;\nconst 函数成员不能修改数据成员\n\n```cpp\n类关键词 类标识符 {\n 访问说明符:(可选)\n 数据成员声明序列;\n 函数成员声明序列;\n};\n```\n\n例:\n\n```cpp\n/* DATE.hpp*/\nclass DATE {\npublic:\nvoid Set( int, int, int );\nint getMonth() const;\nvoid Increment();\nprivate:\nint month;\n};\n```\n\n**<font color=red>成员函数可以定义在类定义内部,或者单独使用作用域解析运算符 :: 来定义</font>**\n例:\n\n```cpp\nclass DATE {\npublic:\nvoid Set(int newYear, int newMonth, int newDay );\nprivate:\n};\nvoid DATE::Set(int newYear, int newMonth, int newDay ) {\nmonth = newMonth;\nday = newDay;\nyear = newYear;\n}\n```\n\n## 静态成员变量与非静态成员变量\n\n| 特性 | 静态成员变量 | 非静态成员变量 |\n| ---------- | --------------------------- | ---------------------- |\n| 存储位置 | 全局数据区 | 对象内存空间 |\n| 生命周期 | 程序运行期间 | 随对象创建和销毁 |\n| 共享性 | 所有对象共享同一份数据 | 每个对象有独立副本 |\n| 初始化位置 | 类外(const static 可类内) | 构造函数或类内初始化器 |\n| 访问方式 | 通过类名或对象访问 | 必须通过对象访问 |\n| 线程安全 | 需额外同步机制(因共享) | 通常线程安全(因独立) |\n\n静态成员变量属于整个类。\n\n## 静态成员函数和非静态成员函数\n\n### 访问权限与作用范围\n\n**静态成员函数**\n 仅访问静态成员:只能操作类的静态成员变量和静态成员函数,无法直接访问非静态成员(因其不绑定任何对象实例)。\n 无 this 指针:静态函数没有隐含的 this 参数,因此无法通过 this->访问实例成员。\n**非静态成员函数**\n 访问所有成员:可自由访问类的静态和非静态成员,包括调用其他非静态函数。\n 隐含 this 指针:通过 this 指针隐式操作当前对象的数据\n\n## 调用方式\n\n**静态成员函数**\n 无需对象实例:可通过类名直接调用,如`ClassName::staticFunc()`,也可通过对象调用(不推荐)。\n**非静态成员函数**\n 必须依赖对象:必须通过对象实例调用,如`obj.nonStaticFunc()`,否则无法执行。\n\n## 内存与生命周期\n\n**静态成员函数**\n 全局存储:属于类本身,在程序启动时即存在,生命周期与程序一致。\n 不增加对象大小:静态函数不占用对象内存空间,sizeof(对象)不包含其信息。\n**非静态成员函数**\n 对象内存关联:每个对象实例拥有独立的非静态成员函数入口地址,但实际代码段共享同一份实现。\n 随对象销毁失效:函数调用依赖于对象的生命周期。\n\n```cpp\nclass MyClass {\npublic:\n static int staticVar; // 静态成员变量\n int nonStaticVar; // 非静态成员变量\n static void staticFunc() {\n staticVar = 10; // ✔️ 可访问静态成员\n // nonStaticVar = 20; ❌ 无法访问非静态成员\n }\n void nonStaticFunc() {\n staticVar = 30; // ✔️ 可访问静态成员\n nonStaticVar = 40; // ✔️ 可访问非静态成员\n }\n};\nint MyClass::staticVar = 0;\nint main() {\n MyClass::staticFunc(); // 直接通过类名调用静态函数\n MyClass obj;\n obj.nonStaticFunc(); // 必须通过对象调用非静态函数\n return 0;\n}\n```\n","source":"_posts/third-blog.md","raw":"---\ntitle: 数据抽象与类\ntags: C++\ntop_img: transparent\ncomments: false\n---\n\n# 数据抽象与类\n\n## 抽象数据类型\n\n1.抽象是从众多的事物中抽取出共同的、本质性的特征,而舍弃其非本质的特征的过程。\n\n2.抽象的过程在于透过事物的现象获得它的本质,并用概念、原理、规律的形式描述它。\n\n3.抽象的意义在于通过事物的本质,识别或区分事物\n\n## 类的声明\n\n### 类关键词\n\n**class 或 struct 或 union **\n用 class 定义的类,默认访问权限为`private`\n用 struct 定义的结构体,默认访问权限为`public`\n\n### 访问说明符\n\n• `public` 公有,表示后续成员是对象使用者可访问\n\n• `private` 私有,表示后续成员仅对象内部可访问\n\n• `protected` 受保护\n\n### 类成员\n\n• 数据成员,按声明顺序存储,对齐规则同 C。\n一般设计中,数据成员需要隐藏保护,需要通过函数成员访问\n\n• 函数成员,公有成员可以被外部使用者访问;\n私有成员仅内部访问;\nconst 函数成员不能修改数据成员\n\n```cpp\n类关键词 类标识符 {\n 访问说明符:(可选)\n 数据成员声明序列;\n 函数成员声明序列;\n};\n```\n\n例:\n\n```cpp\n/* DATE.hpp*/\nclass DATE {\npublic:\nvoid Set( int, int, int );\nint getMonth() const;\nvoid Increment();\nprivate:\nint month;\n};\n```\n\n**<font color=red>成员函数可以定义在类定义内部,或者单独使用作用域解析运算符 :: 来定义</font>**\n例:\n\n```cpp\nclass DATE {\npublic:\nvoid Set(int newYear, int newMonth, int newDay );\nprivate:\n};\nvoid DATE::Set(int newYear, int newMonth, int newDay ) {\nmonth = newMonth;\nday = newDay;\nyear = newYear;\n}\n```\n\n## 静态成员变量与非静态成员变量\n\n| 特性 | 静态成员变量 | 非静态成员变量 |\n| ---------- | --------------------------- | ---------------------- |\n| 存储位置 | 全局数据区 | 对象内存空间 |\n| 生命周期 | 程序运行期间 | 随对象创建和销毁 |\n| 共享性 | 所有对象共享同一份数据 | 每个对象有独立副本 |\n| 初始化位置 | 类外(const static 可类内) | 构造函数或类内初始化器 |\n| 访问方式 | 通过类名或对象访问 | 必须通过对象访问 |\n| 线程安全 | 需额外同步机制(因共享) | 通常线程安全(因独立) |\n\n静态成员变量属于整个类。\n\n## 静态成员函数和非静态成员函数\n\n### 访问权限与作用范围\n\n**静态成员函数**\n 仅访问静态成员:只能操作类的静态成员变量和静态成员函数,无法直接访问非静态成员(因其不绑定任何对象实例)。\n 无 this 指针:静态函数没有隐含的 this 参数,因此无法通过 this->访问实例成员。\n**非静态成员函数**\n 访问所有成员:可自由访问类的静态和非静态成员,包括调用其他非静态函数。\n 隐含 this 指针:通过 this 指针隐式操作当前对象的数据\n\n## 调用方式\n\n**静态成员函数**\n 无需对象实例:可通过类名直接调用,如`ClassName::staticFunc()`,也可通过对象调用(不推荐)。\n**非静态成员函数**\n 必须依赖对象:必须通过对象实例调用,如`obj.nonStaticFunc()`,否则无法执行。\n\n## 内存与生命周期\n\n**静态成员函数**\n 全局存储:属于类本身,在程序启动时即存在,生命周期与程序一致。\n 不增加对象大小:静态函数不占用对象内存空间,sizeof(对象)不包含其信息。\n**非静态成员函数**\n 对象内存关联:每个对象实例拥有独立的非静态成员函数入口地址,但实际代码段共享同一份实现。\n 随对象销毁失效:函数调用依赖于对象的生命周期。\n\n```cpp\nclass MyClass {\npublic:\n static int staticVar; // 静态成员变量\n int nonStaticVar; // 非静态成员变量\n static void staticFunc() {\n staticVar = 10; // ✔️ 可访问静态成员\n // nonStaticVar = 20; ❌ 无法访问非静态成员\n }\n void nonStaticFunc() {\n staticVar = 30; // ✔️ 可访问静态成员\n nonStaticVar = 40; // ✔️ 可访问非静态成员\n }\n};\nint MyClass::staticVar = 0;\nint main() {\n MyClass::staticFunc(); // 直接通过类名调用静态函数\n MyClass obj;\n obj.nonStaticFunc(); // 必须通过对象调用非静态函数\n return 0;\n}\n```\n","slug":"third-blog","published":1,"date":"2025-03-11T13:43:32.205Z","updated":"2025-03-11T13:43:55.558Z","layout":"post","photos":[],"_id":"cmkmd8tz1000qcw64h2tp4g9l","content":"<link rel=\"stylesheet\" class=\"aplayer-secondary-style-marker\" href=\"\\assets\\css\\APlayer.min.css\"><script src=\"\\assets\\js\\APlayer.min.js\" class=\"aplayer-secondary-script-marker\"></script><h1 id=\"数据抽象与类\"><a href=\"#数据抽象与类\" class=\"headerlink\" title=\"数据抽象与类\"></a>数据抽象与类</h1><h2 id=\"抽象数据类型\"><a href=\"#抽象数据类型\" class=\"headerlink\" title=\"抽象数据类型\"></a>抽象数据类型</h2><p>1.抽象是从众多的事物中抽取出共同的、本质性的特征,而舍弃其非本质的特征的过程。</p>\n<p>2.抽象的过程在于透过事物的现象获得它的本质,并用概念、原理、规律的形式描述它。</p>\n<p>3.抽象的意义在于通过事物的本质,识别或区分事物</p>\n<h2 id=\"类的声明\"><a href=\"#类的声明\" class=\"headerlink\" title=\"类的声明\"></a>类的声明</h2><h3 id=\"类关键词\"><a href=\"#类关键词\" class=\"headerlink\" title=\"类关键词\"></a>类关键词</h3><p>**class 或 struct 或 union **<br>用 class 定义的类,默认访问权限为<code>private</code><br>用 struct 定义的结构体,默认访问权限为<code>public</code></p>\n<h3 id=\"访问说明符\"><a href=\"#访问说明符\" class=\"headerlink\" title=\"访问说明符\"></a>访问说明符</h3><p>• <code>public</code> 公有,表示后续成员是对象使用者可访问</p>\n<p>• <code>private</code> 私有,表示后续成员仅对象内部可访问</p>\n<p>• <code>protected</code> 受保护</p>\n<h3 id=\"类成员\"><a href=\"#类成员\" class=\"headerlink\" title=\"类成员\"></a>类成员</h3><p>• 数据成员,按声明顺序存储,对齐规则同 C。<br>一般设计中,数据成员需要隐藏保护,需要通过函数成员访问</p>\n<p>• 函数成员,公有成员可以被外部使用者访问;<br>私有成员仅内部访问;<br>const 函数成员不能修改数据成员</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\">类关键词 类标识符 {</span><br><span class=\"line\"> 访问说明符:(可选)</span><br><span class=\"line\"> 数据成员声明序列;</span><br><span class=\"line\"> 函数成员声明序列;</span><br><span class=\"line\">};</span><br></pre></td></tr></table></figure>\n\n<p>例:</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">/* DATE.hpp*/</span></span><br><span class=\"line\"><span class=\"keyword\">class</span> <span class=\"title class_\">DATE</span> {</span><br><span class=\"line\"><span class=\"keyword\">public</span>:</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">void</span> <span class=\"title\">Set</span><span class=\"params\">( <span class=\"type\">int</span>, <span class=\"type\">int</span>, <span class=\"type\">int</span> )</span></span>;</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">getMonth</span><span class=\"params\">()</span> <span class=\"type\">const</span></span>;</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">void</span> <span class=\"title\">Increment</span><span class=\"params\">()</span></span>;</span><br><span class=\"line\"><span class=\"keyword\">private</span>:</span><br><span class=\"line\"><span class=\"type\">int</span> month;</span><br><span class=\"line\">};</span><br></pre></td></tr></table></figure>\n\n<p><strong><font color=red>成员函数可以定义在类定义内部,或者单独使用作用域解析运算符 :: 来定义</font></strong><br>例:</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">class</span> <span class=\"title class_\">DATE</span> {</span><br><span class=\"line\"><span class=\"keyword\">public</span>:</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">void</span> <span class=\"title\">Set</span><span class=\"params\">(<span class=\"type\">int</span> newYear, <span class=\"type\">int</span> newMonth, <span class=\"type\">int</span> newDay )</span></span>;</span><br><span class=\"line\"><span class=\"keyword\">private</span>:</span><br><span class=\"line\">};</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">void</span> <span class=\"title\">DATE::Set</span><span class=\"params\">(<span class=\"type\">int</span> newYear, <span class=\"type\">int</span> newMonth, <span class=\"type\">int</span> newDay )</span> </span>{</span><br><span class=\"line\">month = newMonth;</span><br><span class=\"line\">day = newDay;</span><br><span class=\"line\">year = newYear;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<h2 id=\"静态成员变量与非静态成员变量\"><a href=\"#静态成员变量与非静态成员变量\" class=\"headerlink\" title=\"静态成员变量与非静态成员变量\"></a>静态成员变量与非静态成员变量</h2><table>\n<thead>\n<tr>\n<th>特性</th>\n<th>静态成员变量</th>\n<th>非静态成员变量</th>\n</tr>\n</thead>\n<tbody><tr>\n<td>存储位置</td>\n<td>全局数据区</td>\n<td>对象内存空间</td>\n</tr>\n<tr>\n<td>生命周期</td>\n<td>程序运行期间</td>\n<td>随对象创建和销毁</td>\n</tr>\n<tr>\n<td>共享性</td>\n<td>所有对象共享同一份数据</td>\n<td>每个对象有独立副本</td>\n</tr>\n<tr>\n<td>初始化位置</td>\n<td>类外(const static 可类内)</td>\n<td>构造函数或类内初始化器</td>\n</tr>\n<tr>\n<td>访问方式</td>\n<td>通过类名或对象访问</td>\n<td>必须通过对象访问</td>\n</tr>\n<tr>\n<td>线程安全</td>\n<td>需额外同步机制(因共享)</td>\n<td>通常线程安全(因独立)</td>\n</tr>\n</tbody></table>\n<p>静态成员变量属于整个类。</p>\n<h2 id=\"静态成员函数和非静态成员函数\"><a href=\"#静态成员函数和非静态成员函数\" class=\"headerlink\" title=\"静态成员函数和非静态成员函数\"></a>静态成员函数和非静态成员函数</h2><h3 id=\"访问权限与作用范围\"><a href=\"#访问权限与作用范围\" class=\"headerlink\" title=\"访问权限与作用范围\"></a>访问权限与作用范围</h3><p><strong>静态成员函数</strong><br> 仅访问静态成员:只能操作类的静态成员变量和静态成员函数,无法直接访问非静态成员(因其不绑定任何对象实例)。<br> 无 this 指针:静态函数没有隐含的 this 参数,因此无法通过 this->访问实例成员。<br><strong>非静态成员函数</strong><br> 访问所有成员:可自由访问类的静态和非静态成员,包括调用其他非静态函数。<br> 隐含 this 指针:通过 this 指针隐式操作当前对象的数据</p>\n<h2 id=\"调用方式\"><a href=\"#调用方式\" class=\"headerlink\" title=\"调用方式\"></a>调用方式</h2><p><strong>静态成员函数</strong><br> 无需对象实例:可通过类名直接调用,如<code>ClassName::staticFunc()</code>,也可通过对象调用(不推荐)。<br><strong>非静态成员函数</strong><br> 必须依赖对象:必须通过对象实例调用,如<code>obj.nonStaticFunc()</code>,否则无法执行。</p>\n<h2 id=\"内存与生命周期\"><a href=\"#内存与生命周期\" class=\"headerlink\" title=\"内存与生命周期\"></a>内存与生命周期</h2><p><strong>静态成员函数</strong><br> 全局存储:属于类本身,在程序启动时即存在,生命周期与程序一致。<br> 不增加对象大小:静态函数不占用对象内存空间,sizeof(对象)不包含其信息。<br><strong>非静态成员函数</strong><br> 对象内存关联:每个对象实例拥有独立的非静态成员函数入口地址,但实际代码段共享同一份实现。<br> 随对象销毁失效:函数调用依赖于对象的生命周期。</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">class</span> <span class=\"title class_\">MyClass</span> {</span><br><span class=\"line\"><span class=\"keyword\">public</span>:</span><br><span class=\"line\"> <span class=\"type\">static</span> <span class=\"type\">int</span> staticVar; <span class=\"comment\">// 静态成员变量</span></span><br><span class=\"line\"> <span class=\"type\">int</span> nonStaticVar; <span class=\"comment\">// 非静态成员变量</span></span><br><span class=\"line\"> <span class=\"function\"><span class=\"type\">static</span> <span class=\"type\">void</span> <span class=\"title\">staticFunc</span><span class=\"params\">()</span> </span>{</span><br><span class=\"line\"> staticVar = <span class=\"number\">10</span>; <span class=\"comment\">// ✔️ 可访问静态成员</span></span><br><span class=\"line\"> <span class=\"comment\">// nonStaticVar = 20; ❌ 无法访问非静态成员</span></span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"function\"><span class=\"type\">void</span> <span class=\"title\">nonStaticFunc</span><span class=\"params\">()</span> </span>{</span><br><span class=\"line\"> staticVar = <span class=\"number\">30</span>; <span class=\"comment\">// ✔️ 可访问静态成员</span></span><br><span class=\"line\"> nonStaticVar = <span class=\"number\">40</span>; <span class=\"comment\">// ✔️ 可访问非静态成员</span></span><br><span class=\"line\"> }</span><br><span class=\"line\">};</span><br><span class=\"line\"><span class=\"type\">int</span> MyClass::staticVar = <span class=\"number\">0</span>;</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span><span class=\"params\">()</span> </span>{</span><br><span class=\"line\"> MyClass::<span class=\"built_in\">staticFunc</span>(); <span class=\"comment\">// 直接通过类名调用静态函数</span></span><br><span class=\"line\"> MyClass obj;</span><br><span class=\"line\"> obj.<span class=\"built_in\">nonStaticFunc</span>(); <span class=\"comment\">// 必须通过对象调用非静态函数</span></span><br><span class=\"line\"> <span class=\"keyword\">return</span> <span class=\"number\">0</span>;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n","excerpt":"","more":"<h1 id=\"数据抽象与类\"><a href=\"#数据抽象与类\" class=\"headerlink\" title=\"数据抽象与类\"></a>数据抽象与类</h1><h2 id=\"抽象数据类型\"><a href=\"#抽象数据类型\" class=\"headerlink\" title=\"抽象数据类型\"></a>抽象数据类型</h2><p>1.抽象是从众多的事物中抽取出共同的、本质性的特征,而舍弃其非本质的特征的过程。</p>\n<p>2.抽象的过程在于透过事物的现象获得它的本质,并用概念、原理、规律的形式描述它。</p>\n<p>3.抽象的意义在于通过事物的本质,识别或区分事物</p>\n<h2 id=\"类的声明\"><a href=\"#类的声明\" class=\"headerlink\" title=\"类的声明\"></a>类的声明</h2><h3 id=\"类关键词\"><a href=\"#类关键词\" class=\"headerlink\" title=\"类关键词\"></a>类关键词</h3><p>**class 或 struct 或 union **<br>用 class 定义的类,默认访问权限为<code>private</code><br>用 struct 定义的结构体,默认访问权限为<code>public</code></p>\n<h3 id=\"访问说明符\"><a href=\"#访问说明符\" class=\"headerlink\" title=\"访问说明符\"></a>访问说明符</h3><p>• <code>public</code> 公有,表示后续成员是对象使用者可访问</p>\n<p>• <code>private</code> 私有,表示后续成员仅对象内部可访问</p>\n<p>• <code>protected</code> 受保护</p>\n<h3 id=\"类成员\"><a href=\"#类成员\" class=\"headerlink\" title=\"类成员\"></a>类成员</h3><p>• 数据成员,按声明顺序存储,对齐规则同 C。<br>一般设计中,数据成员需要隐藏保护,需要通过函数成员访问</p>\n<p>• 函数成员,公有成员可以被外部使用者访问;<br>私有成员仅内部访问;<br>const 函数成员不能修改数据成员</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\">类关键词 类标识符 {</span><br><span class=\"line\"> 访问说明符:(可选)</span><br><span class=\"line\"> 数据成员声明序列;</span><br><span class=\"line\"> 函数成员声明序列;</span><br><span class=\"line\">};</span><br></pre></td></tr></table></figure>\n\n<p>例:</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">/* DATE.hpp*/</span></span><br><span class=\"line\"><span class=\"keyword\">class</span> <span class=\"title class_\">DATE</span> {</span><br><span class=\"line\"><span class=\"keyword\">public</span>:</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">void</span> <span class=\"title\">Set</span><span class=\"params\">( <span class=\"type\">int</span>, <span class=\"type\">int</span>, <span class=\"type\">int</span> )</span></span>;</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">getMonth</span><span class=\"params\">()</span> <span class=\"type\">const</span></span>;</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">void</span> <span class=\"title\">Increment</span><span class=\"params\">()</span></span>;</span><br><span class=\"line\"><span class=\"keyword\">private</span>:</span><br><span class=\"line\"><span class=\"type\">int</span> month;</span><br><span class=\"line\">};</span><br></pre></td></tr></table></figure>\n\n<p><strong><font color=red>成员函数可以定义在类定义内部,或者单独使用作用域解析运算符 :: 来定义</font></strong><br>例:</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">class</span> <span class=\"title class_\">DATE</span> {</span><br><span class=\"line\"><span class=\"keyword\">public</span>:</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">void</span> <span class=\"title\">Set</span><span class=\"params\">(<span class=\"type\">int</span> newYear, <span class=\"type\">int</span> newMonth, <span class=\"type\">int</span> newDay )</span></span>;</span><br><span class=\"line\"><span class=\"keyword\">private</span>:</span><br><span class=\"line\">};</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">void</span> <span class=\"title\">DATE::Set</span><span class=\"params\">(<span class=\"type\">int</span> newYear, <span class=\"type\">int</span> newMonth, <span class=\"type\">int</span> newDay )</span> </span>{</span><br><span class=\"line\">month = newMonth;</span><br><span class=\"line\">day = newDay;</span><br><span class=\"line\">year = newYear;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<h2 id=\"静态成员变量与非静态成员变量\"><a href=\"#静态成员变量与非静态成员变量\" class=\"headerlink\" title=\"静态成员变量与非静态成员变量\"></a>静态成员变量与非静态成员变量</h2><table>\n<thead>\n<tr>\n<th>特性</th>\n<th>静态成员变量</th>\n<th>非静态成员变量</th>\n</tr>\n</thead>\n<tbody><tr>\n<td>存储位置</td>\n<td>全局数据区</td>\n<td>对象内存空间</td>\n</tr>\n<tr>\n<td>生命周期</td>\n<td>程序运行期间</td>\n<td>随对象创建和销毁</td>\n</tr>\n<tr>\n<td>共享性</td>\n<td>所有对象共享同一份数据</td>\n<td>每个对象有独立副本</td>\n</tr>\n<tr>\n<td>初始化位置</td>\n<td>类外(const static 可类内)</td>\n<td>构造函数或类内初始化器</td>\n</tr>\n<tr>\n<td>访问方式</td>\n<td>通过类名或对象访问</td>\n<td>必须通过对象访问</td>\n</tr>\n<tr>\n<td>线程安全</td>\n<td>需额外同步机制(因共享)</td>\n<td>通常线程安全(因独立)</td>\n</tr>\n</tbody></table>\n<p>静态成员变量属于整个类。</p>\n<h2 id=\"静态成员函数和非静态成员函数\"><a href=\"#静态成员函数和非静态成员函数\" class=\"headerlink\" title=\"静态成员函数和非静态成员函数\"></a>静态成员函数和非静态成员函数</h2><h3 id=\"访问权限与作用范围\"><a href=\"#访问权限与作用范围\" class=\"headerlink\" title=\"访问权限与作用范围\"></a>访问权限与作用范围</h3><p><strong>静态成员函数</strong><br> 仅访问静态成员:只能操作类的静态成员变量和静态成员函数,无法直接访问非静态成员(因其不绑定任何对象实例)。<br> 无 this 指针:静态函数没有隐含的 this 参数,因此无法通过 this->访问实例成员。<br><strong>非静态成员函数</strong><br> 访问所有成员:可自由访问类的静态和非静态成员,包括调用其他非静态函数。<br> 隐含 this 指针:通过 this 指针隐式操作当前对象的数据</p>\n<h2 id=\"调用方式\"><a href=\"#调用方式\" class=\"headerlink\" title=\"调用方式\"></a>调用方式</h2><p><strong>静态成员函数</strong><br> 无需对象实例:可通过类名直接调用,如<code>ClassName::staticFunc()</code>,也可通过对象调用(不推荐)。<br><strong>非静态成员函数</strong><br> 必须依赖对象:必须通过对象实例调用,如<code>obj.nonStaticFunc()</code>,否则无法执行。</p>\n<h2 id=\"内存与生命周期\"><a href=\"#内存与生命周期\" class=\"headerlink\" title=\"内存与生命周期\"></a>内存与生命周期</h2><p><strong>静态成员函数</strong><br> 全局存储:属于类本身,在程序启动时即存在,生命周期与程序一致。<br> 不增加对象大小:静态函数不占用对象内存空间,sizeof(对象)不包含其信息。<br><strong>非静态成员函数</strong><br> 对象内存关联:每个对象实例拥有独立的非静态成员函数入口地址,但实际代码段共享同一份实现。<br> 随对象销毁失效:函数调用依赖于对象的生命周期。</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">class</span> <span class=\"title class_\">MyClass</span> {</span><br><span class=\"line\"><span class=\"keyword\">public</span>:</span><br><span class=\"line\"> <span class=\"type\">static</span> <span class=\"type\">int</span> staticVar; <span class=\"comment\">// 静态成员变量</span></span><br><span class=\"line\"> <span class=\"type\">int</span> nonStaticVar; <span class=\"comment\">// 非静态成员变量</span></span><br><span class=\"line\"> <span class=\"function\"><span class=\"type\">static</span> <span class=\"type\">void</span> <span class=\"title\">staticFunc</span><span class=\"params\">()</span> </span>{</span><br><span class=\"line\"> staticVar = <span class=\"number\">10</span>; <span class=\"comment\">// ✔️ 可访问静态成员</span></span><br><span class=\"line\"> <span class=\"comment\">// nonStaticVar = 20; ❌ 无法访问非静态成员</span></span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"function\"><span class=\"type\">void</span> <span class=\"title\">nonStaticFunc</span><span class=\"params\">()</span> </span>{</span><br><span class=\"line\"> staticVar = <span class=\"number\">30</span>; <span class=\"comment\">// ✔️ 可访问静态成员</span></span><br><span class=\"line\"> nonStaticVar = <span class=\"number\">40</span>; <span class=\"comment\">// ✔️ 可访问非静态成员</span></span><br><span class=\"line\"> }</span><br><span class=\"line\">};</span><br><span class=\"line\"><span class=\"type\">int</span> MyClass::staticVar = <span class=\"number\">0</span>;</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">main</span><span class=\"params\">()</span> </span>{</span><br><span class=\"line\"> MyClass::<span class=\"built_in\">staticFunc</span>(); <span class=\"comment\">// 直接通过类名调用静态函数</span></span><br><span class=\"line\"> MyClass obj;</span><br><span class=\"line\"> obj.<span class=\"built_in\">nonStaticFunc</span>(); <span class=\"comment\">// 必须通过对象调用非静态函数</span></span><br><span class=\"line\"> <span class=\"keyword\">return</span> <span class=\"number\">0</span>;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n"},{"title":"动态规划(dp)","top_img":"transparent","comments":0,"_content":"\n# 动态规划\n\n## 核心原理\n\n### 重叠子问题\n\n在递归分解问题时,相同子问题会被多次重复计算。例如,斐波那契数列中计算 F(5)需要多次计算 F(3),动态规划通过缓存子问题解(如数组或哈希表)避免重复计算\n\n### 最优子结构\n\n问题的最优解可以由其子问题的最优解组合而成。例如,最短路径问题中,从 A 到 B 的最短路径必然包含中间点 C 的最短路径\n\n### 状态转移方程\n\n定义状态之间的关系式,明确如何从子问题推导出当前问题的解。\n例如,0-1 背包问题的状态转移方程为:\n\n```cpp\ndp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]] + v[i])\n```\n\n## 实现步骤\n\n1.定义状态\n\n2.初始化边界条件\n\n3.推导状态转移方程\n\n4.计算顺序与填表\n\n## 实现方式\n\n1.自底向上迭代(推荐)\n通过循环逐步填充状态表,适合线性问题。例如,计算斐波那契数列:\n\n```cpp\nint fib(int n) {\n if (n <= 1) return n;\n int dp[n+1];\n dp[0] = 0, dp[1] = 1;\n for (int i = 2; i <= n; i++) {\n dp[i] = dp[i-1] + dp[i-2];\n }\n return dp[n];\n}\n```\n\n2.自顶向下递归(记忆化)\n通过递归分解问题,并用缓存避免重复计算。例如:\n\n```cpp\nvector<int> memo(n+1, -1);\nint fib(int n) {\n if (n <= 1) return n;\n if (memo[n] != -1) return memo[n];\n memo[n] = fib(n-1) + fib(n-2);\n return memo[n];\n}\n```\n\n3.空间优化(滚动数组)\n对于某些问题(如背包问题),可将二维数组优化为一维。例如,0-1 背包的滚动数组实现:\n\n```cpp\nint knapsack(vector<int>& w, vector<int>& v, int C) {\n vector<int> dp(C+1, 0);\n for (int i = 0; i < w.size(); i++) {\n for (int j = C; j >= w[i]; j--) { // 逆序遍历避免覆盖\n dp[j] = max(dp[j], dp[j - w[i]] + v[i]);\n }\n }\n return dp[C];\n}\n```\n\n## 经典问题\n\n1.爬楼梯问题\n\n2.0-1 背包问题\n\n3.最长公共子序列(LCS)\n状态转移方程为:\n\n```cpp\ndp[i][j] = (s1[i] == s2[j]) ? dp[i-1][j-1] + 1 : max(dp[i-1][j], dp[i][j-1])\n```\n","source":"_posts/forth-blog.md","raw":"---\ntitle: 动态规划(dp)\ntags: 算法\ntop_img: transparent\ncomments: false\n---\n\n# 动态规划\n\n## 核心原理\n\n### 重叠子问题\n\n在递归分解问题时,相同子问题会被多次重复计算。例如,斐波那契数列中计算 F(5)需要多次计算 F(3),动态规划通过缓存子问题解(如数组或哈希表)避免重复计算\n\n### 最优子结构\n\n问题的最优解可以由其子问题的最优解组合而成。例如,最短路径问题中,从 A 到 B 的最短路径必然包含中间点 C 的最短路径\n\n### 状态转移方程\n\n定义状态之间的关系式,明确如何从子问题推导出当前问题的解。\n例如,0-1 背包问题的状态转移方程为:\n\n```cpp\ndp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]] + v[i])\n```\n\n## 实现步骤\n\n1.定义状态\n\n2.初始化边界条件\n\n3.推导状态转移方程\n\n4.计算顺序与填表\n\n## 实现方式\n\n1.自底向上迭代(推荐)\n通过循环逐步填充状态表,适合线性问题。例如,计算斐波那契数列:\n\n```cpp\nint fib(int n) {\n if (n <= 1) return n;\n int dp[n+1];\n dp[0] = 0, dp[1] = 1;\n for (int i = 2; i <= n; i++) {\n dp[i] = dp[i-1] + dp[i-2];\n }\n return dp[n];\n}\n```\n\n2.自顶向下递归(记忆化)\n通过递归分解问题,并用缓存避免重复计算。例如:\n\n```cpp\nvector<int> memo(n+1, -1);\nint fib(int n) {\n if (n <= 1) return n;\n if (memo[n] != -1) return memo[n];\n memo[n] = fib(n-1) + fib(n-2);\n return memo[n];\n}\n```\n\n3.空间优化(滚动数组)\n对于某些问题(如背包问题),可将二维数组优化为一维。例如,0-1 背包的滚动数组实现:\n\n```cpp\nint knapsack(vector<int>& w, vector<int>& v, int C) {\n vector<int> dp(C+1, 0);\n for (int i = 0; i < w.size(); i++) {\n for (int j = C; j >= w[i]; j--) { // 逆序遍历避免覆盖\n dp[j] = max(dp[j], dp[j - w[i]] + v[i]);\n }\n }\n return dp[C];\n}\n```\n\n## 经典问题\n\n1.爬楼梯问题\n\n2.0-1 背包问题\n\n3.最长公共子序列(LCS)\n状态转移方程为:\n\n```cpp\ndp[i][j] = (s1[i] == s2[j]) ? dp[i-1][j-1] + 1 : max(dp[i-1][j], dp[i][j-1])\n```\n","slug":"forth-blog","published":1,"date":"2025-03-13T08:02:06.555Z","updated":"2025-03-13T08:03:59.890Z","layout":"post","photos":[],"_id":"cmkmd8tz1000rcw6432vzaofx","content":"<link rel=\"stylesheet\" class=\"aplayer-secondary-style-marker\" href=\"\\assets\\css\\APlayer.min.css\"><script src=\"\\assets\\js\\APlayer.min.js\" class=\"aplayer-secondary-script-marker\"></script><h1 id=\"动态规划\"><a href=\"#动态规划\" class=\"headerlink\" title=\"动态规划\"></a>动态规划</h1><h2 id=\"核心原理\"><a href=\"#核心原理\" class=\"headerlink\" title=\"核心原理\"></a>核心原理</h2><h3 id=\"重叠子问题\"><a href=\"#重叠子问题\" class=\"headerlink\" title=\"重叠子问题\"></a>重叠子问题</h3><p>在递归分解问题时,相同子问题会被多次重复计算。例如,斐波那契数列中计算 F(5)需要多次计算 F(3),动态规划通过缓存子问题解(如数组或哈希表)避免重复计算</p>\n<h3 id=\"最优子结构\"><a href=\"#最优子结构\" class=\"headerlink\" title=\"最优子结构\"></a>最优子结构</h3><p>问题的最优解可以由其子问题的最优解组合而成。例如,最短路径问题中,从 A 到 B 的最短路径必然包含中间点 C 的最短路径</p>\n<h3 id=\"状态转移方程\"><a href=\"#状态转移方程\" class=\"headerlink\" title=\"状态转移方程\"></a>状态转移方程</h3><p>定义状态之间的关系式,明确如何从子问题推导出当前问题的解。<br>例如,0-1 背包问题的状态转移方程为:</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\">dp[i][j] = <span class=\"built_in\">max</span>(dp[i<span class=\"number\">-1</span>][j], dp[i<span class=\"number\">-1</span>][j-w[i]] + v[i])</span><br></pre></td></tr></table></figure>\n\n<h2 id=\"实现步骤\"><a href=\"#实现步骤\" class=\"headerlink\" title=\"实现步骤\"></a>实现步骤</h2><p>1.定义状态</p>\n<p>2.初始化边界条件</p>\n<p>3.推导状态转移方程</p>\n<p>4.计算顺序与填表</p>\n<h2 id=\"实现方式\"><a href=\"#实现方式\" class=\"headerlink\" title=\"实现方式\"></a>实现方式</h2><p>1.自底向上迭代(推荐)<br>通过循环逐步填充状态表,适合线性问题。例如,计算斐波那契数列:</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">fib</span><span class=\"params\">(<span class=\"type\">int</span> n)</span> </span>{</span><br><span class=\"line\"> <span class=\"keyword\">if</span> (n <= <span class=\"number\">1</span>) <span class=\"keyword\">return</span> n;</span><br><span class=\"line\"> <span class=\"type\">int</span> dp[n<span class=\"number\">+1</span>];</span><br><span class=\"line\"> dp[<span class=\"number\">0</span>] = <span class=\"number\">0</span>, dp[<span class=\"number\">1</span>] = <span class=\"number\">1</span>;</span><br><span class=\"line\"> <span class=\"keyword\">for</span> (<span class=\"type\">int</span> i = <span class=\"number\">2</span>; i <= n; i++) {</span><br><span class=\"line\"> dp[i] = dp[i<span class=\"number\">-1</span>] + dp[i<span class=\"number\">-2</span>];</span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"keyword\">return</span> dp[n];</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<p>2.自顶向下递归(记忆化)<br>通过递归分解问题,并用缓存避免重复计算。例如:</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"function\">vector<<span class=\"type\">int</span>> <span class=\"title\">memo</span><span class=\"params\">(n<span class=\"number\">+1</span>, <span class=\"number\">-1</span>)</span></span>;</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">fib</span><span class=\"params\">(<span class=\"type\">int</span> n)</span> </span>{</span><br><span class=\"line\"> <span class=\"keyword\">if</span> (n <= <span class=\"number\">1</span>) <span class=\"keyword\">return</span> n;</span><br><span class=\"line\"> <span class=\"keyword\">if</span> (memo[n] != <span class=\"number\">-1</span>) <span class=\"keyword\">return</span> memo[n];</span><br><span class=\"line\"> memo[n] = <span class=\"built_in\">fib</span>(n<span class=\"number\">-1</span>) + <span class=\"built_in\">fib</span>(n<span class=\"number\">-2</span>);</span><br><span class=\"line\"> <span class=\"keyword\">return</span> memo[n];</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<p>3.空间优化(滚动数组)<br>对于某些问题(如背包问题),可将二维数组优化为一维。例如,0-1 背包的滚动数组实现:</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">knapsack</span><span class=\"params\">(vector<<span class=\"type\">int</span>>& w, vector<<span class=\"type\">int</span>>& v, <span class=\"type\">int</span> C)</span> </span>{</span><br><span class=\"line\"> <span class=\"function\">vector<<span class=\"type\">int</span>> <span class=\"title\">dp</span><span class=\"params\">(C<span class=\"number\">+1</span>, <span class=\"number\">0</span>)</span></span>;</span><br><span class=\"line\"> <span class=\"keyword\">for</span> (<span class=\"type\">int</span> i = <span class=\"number\">0</span>; i < w.<span class=\"built_in\">size</span>(); i++) {</span><br><span class=\"line\"> <span class=\"keyword\">for</span> (<span class=\"type\">int</span> j = C; j >= w[i]; j--) { <span class=\"comment\">// 逆序遍历避免覆盖</span></span><br><span class=\"line\"> dp[j] = <span class=\"built_in\">max</span>(dp[j], dp[j - w[i]] + v[i]);</span><br><span class=\"line\"> }</span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"keyword\">return</span> dp[C];</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<h2 id=\"经典问题\"><a href=\"#经典问题\" class=\"headerlink\" title=\"经典问题\"></a>经典问题</h2><p>1.爬楼梯问题</p>\n<p>2.0-1 背包问题</p>\n<p>3.最长公共子序列(LCS)<br>状态转移方程为:</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\">dp[i][j] = (s1[i] == s2[j]) ? dp[i<span class=\"number\">-1</span>][j<span class=\"number\">-1</span>] + <span class=\"number\">1</span> : <span class=\"built_in\">max</span>(dp[i<span class=\"number\">-1</span>][j], dp[i][j<span class=\"number\">-1</span>])</span><br></pre></td></tr></table></figure>\n","excerpt":"","more":"<h1 id=\"动态规划\"><a href=\"#动态规划\" class=\"headerlink\" title=\"动态规划\"></a>动态规划</h1><h2 id=\"核心原理\"><a href=\"#核心原理\" class=\"headerlink\" title=\"核心原理\"></a>核心原理</h2><h3 id=\"重叠子问题\"><a href=\"#重叠子问题\" class=\"headerlink\" title=\"重叠子问题\"></a>重叠子问题</h3><p>在递归分解问题时,相同子问题会被多次重复计算。例如,斐波那契数列中计算 F(5)需要多次计算 F(3),动态规划通过缓存子问题解(如数组或哈希表)避免重复计算</p>\n<h3 id=\"最优子结构\"><a href=\"#最优子结构\" class=\"headerlink\" title=\"最优子结构\"></a>最优子结构</h3><p>问题的最优解可以由其子问题的最优解组合而成。例如,最短路径问题中,从 A 到 B 的最短路径必然包含中间点 C 的最短路径</p>\n<h3 id=\"状态转移方程\"><a href=\"#状态转移方程\" class=\"headerlink\" title=\"状态转移方程\"></a>状态转移方程</h3><p>定义状态之间的关系式,明确如何从子问题推导出当前问题的解。<br>例如,0-1 背包问题的状态转移方程为:</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\">dp[i][j] = <span class=\"built_in\">max</span>(dp[i<span class=\"number\">-1</span>][j], dp[i<span class=\"number\">-1</span>][j-w[i]] + v[i])</span><br></pre></td></tr></table></figure>\n\n<h2 id=\"实现步骤\"><a href=\"#实现步骤\" class=\"headerlink\" title=\"实现步骤\"></a>实现步骤</h2><p>1.定义状态</p>\n<p>2.初始化边界条件</p>\n<p>3.推导状态转移方程</p>\n<p>4.计算顺序与填表</p>\n<h2 id=\"实现方式\"><a href=\"#实现方式\" class=\"headerlink\" title=\"实现方式\"></a>实现方式</h2><p>1.自底向上迭代(推荐)<br>通过循环逐步填充状态表,适合线性问题。例如,计算斐波那契数列:</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">fib</span><span class=\"params\">(<span class=\"type\">int</span> n)</span> </span>{</span><br><span class=\"line\"> <span class=\"keyword\">if</span> (n <= <span class=\"number\">1</span>) <span class=\"keyword\">return</span> n;</span><br><span class=\"line\"> <span class=\"type\">int</span> dp[n<span class=\"number\">+1</span>];</span><br><span class=\"line\"> dp[<span class=\"number\">0</span>] = <span class=\"number\">0</span>, dp[<span class=\"number\">1</span>] = <span class=\"number\">1</span>;</span><br><span class=\"line\"> <span class=\"keyword\">for</span> (<span class=\"type\">int</span> i = <span class=\"number\">2</span>; i <= n; i++) {</span><br><span class=\"line\"> dp[i] = dp[i<span class=\"number\">-1</span>] + dp[i<span class=\"number\">-2</span>];</span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"keyword\">return</span> dp[n];</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<p>2.自顶向下递归(记忆化)<br>通过递归分解问题,并用缓存避免重复计算。例如:</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"function\">vector<<span class=\"type\">int</span>> <span class=\"title\">memo</span><span class=\"params\">(n<span class=\"number\">+1</span>, <span class=\"number\">-1</span>)</span></span>;</span><br><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">fib</span><span class=\"params\">(<span class=\"type\">int</span> n)</span> </span>{</span><br><span class=\"line\"> <span class=\"keyword\">if</span> (n <= <span class=\"number\">1</span>) <span class=\"keyword\">return</span> n;</span><br><span class=\"line\"> <span class=\"keyword\">if</span> (memo[n] != <span class=\"number\">-1</span>) <span class=\"keyword\">return</span> memo[n];</span><br><span class=\"line\"> memo[n] = <span class=\"built_in\">fib</span>(n<span class=\"number\">-1</span>) + <span class=\"built_in\">fib</span>(n<span class=\"number\">-2</span>);</span><br><span class=\"line\"> <span class=\"keyword\">return</span> memo[n];</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<p>3.空间优化(滚动数组)<br>对于某些问题(如背包问题),可将二维数组优化为一维。例如,0-1 背包的滚动数组实现:</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"function\"><span class=\"type\">int</span> <span class=\"title\">knapsack</span><span class=\"params\">(vector<<span class=\"type\">int</span>>& w, vector<<span class=\"type\">int</span>>& v, <span class=\"type\">int</span> C)</span> </span>{</span><br><span class=\"line\"> <span class=\"function\">vector<<span class=\"type\">int</span>> <span class=\"title\">dp</span><span class=\"params\">(C<span class=\"number\">+1</span>, <span class=\"number\">0</span>)</span></span>;</span><br><span class=\"line\"> <span class=\"keyword\">for</span> (<span class=\"type\">int</span> i = <span class=\"number\">0</span>; i < w.<span class=\"built_in\">size</span>(); i++) {</span><br><span class=\"line\"> <span class=\"keyword\">for</span> (<span class=\"type\">int</span> j = C; j >= w[i]; j--) { <span class=\"comment\">// 逆序遍历避免覆盖</span></span><br><span class=\"line\"> dp[j] = <span class=\"built_in\">max</span>(dp[j], dp[j - w[i]] + v[i]);</span><br><span class=\"line\"> }</span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"keyword\">return</span> dp[C];</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n\n<h2 id=\"经典问题\"><a href=\"#经典问题\" class=\"headerlink\" title=\"经典问题\"></a>经典问题</h2><p>1.爬楼梯问题</p>\n<p>2.0-1 背包问题</p>\n<p>3.最长公共子序列(LCS)<br>状态转移方程为:</p>\n<figure class=\"highlight cpp\"><table><tr><td class=\"code\"><pre><span class=\"line\">dp[i][j] = (s1[i] == s2[j]) ? dp[i<span class=\"number\">-1</span>][j<span class=\"number\">-1</span>] + <span class=\"number\">1</span> : <span class=\"built_in\">max</span>(dp[i<span class=\"number\">-1</span>][j], dp[i][j<span class=\"number\">-1</span>])</span><br></pre></td></tr></table></figure>\n"}],"PostAsset":[],"PostCategory":[],"PostTag":[{"post_id":"cmkmd8typ0001cw64fa02ben6","tag_id":"cmkmd8tys0004cw64dm3eha1x","_id":"cmkmd8tyv0009cw64a9rp6x14"},{"post_id":"cmkmd8tyr0003cw645bw24z1q","tag_id":"cmkmd8tys0004cw64dm3eha1x","_id":"cmkmd8tyw000bcw64dbplghih"},{"post_id":"cmkmd8tyt0006cw64fnqq58r3","tag_id":"cmkmd8tyv000acw647bezgjxm","_id":"cmkmd8tyw000dcw648ai27bc7"},{"post_id":"cmkmd8tyu0007cw64667s6ika","tag_id":"cmkmd8tyw000ccw641epw3ozk","_id":"cmkmd8tyw000ecw64andd0pqx"},{"post_id":"cmkmd8tyx000fcw64d7n5go0s","tag_id":"cmkmd8tys0004cw64dm3eha1x","_id":"cmkmd8tyy000hcw643bl5ej9x"},{"post_id":"cmkmd8tyy000gcw64cugdd8we","tag_id":"cmkmd8tys0004cw64dm3eha1x","_id":"cmkmd8tyz000jcw6495xc83ef"},{"post_id":"cmkmd8tyy000icw647u5m6r00","tag_id":"cmkmd8tys0004cw64dm3eha1x","_id":"cmkmd8tz0000lcw64gk2a3gwn"},{"post_id":"cmkmd8tyz000kcw649dly5vw2","tag_id":"cmkmd8tys0004cw64dm3eha1x","_id":"cmkmd8tz0000ncw64eyt28540"},{"post_id":"cmkmd8tz0000mcw64f3t5fxrq","tag_id":"cmkmd8tys0004cw64dm3eha1x","_id":"cmkmd8tz1000pcw64743o6830"},{"post_id":"cmkmd8tz1000qcw64h2tp4g9l","tag_id":"cmkmd8tys0004cw64dm3eha1x","_id":"cmkmd8tz1000scw64h6vghvme"},{"post_id":"cmkmd8tz1000rcw6432vzaofx","tag_id":"cmkmd8tyv000acw647bezgjxm","_id":"cmkmd8tz1000tcw64b2sk8dfc"}],"Tag":[{"name":"C++","_id":"cmkmd8tys0004cw64dm3eha1x"},{"name":"算法","_id":"cmkmd8tyv000acw647bezgjxm"},{"name":"博客构建","_id":"cmkmd8tyw000ccw641epw3ozk"}]}}