-
Notifications
You must be signed in to change notification settings - Fork 29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
3-5. vectorへのemplace_back/push_back説明への違和感 #72
Comments
本件に関して、StackOverflow上の議論 Why would I ever use push_back instead of emplace_back? がありました。 暗黙(implicit)/明示(explicit)コンストラクタの違いにフォーカスした例示があげられています。 std::vector<std::unique_ptr<T>> v;
T a;
v.emplace_back(std::addressof(a)); // compiles
v.push_back(std::addressof(a)); // fails to compile かなりマニアックなケースであることは否めませんが、「すべての |
『ゼロから学ぶC++』はC++11を対象としているので, struct S { std::string a, b; };
std::vector<S> v;
v.push_back({"abc", "xyz"}); // compiles
v.emplace_back("abc", "xyz"); // fails to compile
v.emplace_back({"abc", "xyz"}); // fails to compile
v.emplace_back(S{"abc", "xyz"}); // compiles |
まあ全部のケースでpush_backを置き換えられるわけではないというのはたしかにそうですね。どう修正しましょうか・・・。 ところでClangで下のコード通らないのなんででしょう・・・ #include <string>
#include <vector>
int main()
{
struct S { std::string a, b; };
std::vector<S> v;
v.push_back({"abc", "xyz"}); // compiles
v.emplace_back("abc", "xyz"); // fails to compile
//v.emplace_back({"abc", "xyz"}); // fails to compile
v.emplace_back(S{"abc", "xyz"}); // compiles
} https://wandbox.org/permlink/hmwRtwbKIC8NPC9b
|
StackOverflow回答 Does clang++ 12 support C++20 std::construct_at? によれば、単に未実装のようです。 |
Clang,ちょいちょいC++20サポートが貧弱なので… |
例えば 書籍 Effective Modern C++ では「項目42:要素の挿入の代わりに直接配置を検討する」と紹介されていますね。 素案: C++11より前は push_back という関数のみが末尾への要素追加を担っていました。 C++11で追加された emplace_back は要素型のコンストラクタに直接引数を渡すことができるので push_back と同じかそれ以上のパフォーマンスを得られるケースがあります。両者の最適な使い分けは高度なトピックとなるため、詳細は 書籍 Effective Modern C++ で紹介される「項目42:要素の挿入の代わりに直接配置を検討する」を参照ください。 |
うーん、自分はまず |
改めて書籍 Effective Modern C++(日本語版) の記載を確認してみましたが、yumetodo さん方針では セキュアコーディング の観点から不安が残ります。 前掲のStackOverflow回答にも言及ありますが、 セマンティクス上はコンパイルエラーとなるべき(例えば #include <vector>
#include <regex>
int main()
{
std::vector<std::regex> rv;
rv.emplace_back(nullptr); // 実行時エラー
// rv.push_back(nullptr); // コンパイルエラー
} |
なるほど、そこには頭が回っていなかったですね・・・。 |
#56 で追加された下記ノート(question)は、強すぎる主張により読者の誤解を招く表現になっていると感じます。
emplace_back
が導入されたC++11以降でも、既存変数からのコピー/ムーブを行うといったpush_back
のユースケースは依然として残っています。emplace_back
が有効のなのは、一部のコンテナにおいて巨大な要素オブジェクト型を格納するさいにメモリ確保を効率化できる可能性があるためです(導入当時のMotivation)。その意味では、vector<int>
例示における実質的なemplace_back
/push_back
差異はなく、やはり少々強すぎる主張と思います。訂正:既存変数からのコピー/ムーブは
emplace_back
でも実現可能でした。この部分は取り下げます。The text was updated successfully, but these errors were encountered: