2

次のコード

#include <vector>
#include <string>
#include <iostream>

std::string const& at(std::vector<std::string> const& n, int i)
{
    return n[i];
}

std::vector<std::string> mkvec()
{
    std::vector<std::string> n;
    n.push_back("kagami");
    n.push_back("misao");
    return n;
}

int main()
{
    std::string const& s = at(mkvec(), 0);
    std::cout << s << std::endl; // D'oh!
    return 0;
}

元のベクトルがそこですでに破壊されているため、クラッシュする可能性があります。右辺値参照が導入された後の C++ 2011 (c++0x) では、ベクトル引数が右辺値である場合、削除された関数宣言を使用して呼び出しを完全に禁止できます。at

std::string const& at(std::vector<std::string>&&, int) = delete;

それは良さそうに見えますが、次のコードは依然としてクラッシュを引き起こします

int main()
{
    std::string const& s = mkvec()[0];
    std::cout << s << std::endl; // D'oh!
    return 0;
}

operator [] (size_type) const右辺値オブジェクトのメンバー関数の呼び出しは引き続き許可されるためです。この種の呼び出しを禁止する方法はありますか?

修理:

上記の例は、私が実際のプロジェクトで行ったことではありません。C++ 2011 が次のようなメンバー関数の修飾をサポートしているかどうか疑問に思っています

class A {
    void func() rvalue; // Then a call on an rvalue object goes to this overload
    void func() const;
};

修理:

それは素晴らしいことですが、C++ 標準はこの機能に行き過ぎていると思います。とにかく、clang ++ 2.9でコンパイルされた次のコードがあります

#include <cstdio>

struct A {
    A() {}

    void func() &
    {
        puts("a");
    }

    void func() &&
    {
        puts("b");
    }

    void func() const &
    {
        puts("c");
    }
};

int main()
{
    A().func();
    A a;
    a.func();
    A const b;
    b.func();
    return 0;
}

どうもありがとう!

4

2 に答える 2

6

いいえ、そうすべきではありません。一時的にstd::cout << at(mkvec(), 0) << std::endl;使用することを禁止されている場合、完全に合理的なことですが、どうすればよいですか?at()

残念ながら、一時変数への参照を格納することは、C++ プログラマーが対処しなければならない問題にすぎません。


あなたの新しい質問に答えるには、はい、これを行うことができます:

class A {
    void func() &; // lvalues go to this one
    void func() &&; // rvalues go to this one
};

A a;
a.func(); // first overload

A().func(); // second overload
于 2011-04-28T02:27:20.603 に答える
-1

ただのアイデア:

なんらかの方法でベクターのコンストラクターのコピーを無効にします。

vector ( const vector<T,Allocator>& x );

とにかく、配列の暗黙的なコピーはそれほど良いことではありません。(なぜSTLの作者がそのようなctorを定義することにしたのか疑問に思います)

それはあなたが言及したような問題を修正し、ボーナスとしてあなたにあなたの関数のより効果的なバージョンを使用することを強制します:

void mkvec(std::vector<std::string>& n)
{
    n.push_back("kagami");
    n.push_back("misao");
}
于 2011-04-28T03:09:41.103 に答える