4

ソースを制御できないクラスのインスタンスへの参照を返す関数がある場合は、次のように言いますlist<int>

list<int>& f();

その値が別の参照にのみ割り当てられるようにしたい。

list<int> &a_list = f();

ユーザーが代わりに行う場合:

list<int> a_list = f(); // note: no '&', so the list is copied

ユーザーは元のリストではなく、リストのコピーのみを操作するため、コンパイル時のエラーにしたいと考えています (これは、アプリケーションで意図されている/求められているものではありません)。

上記のコピー構築と割り当てを防ぐ方法はありますか (ある種の「ラッパー」クラスを介して)。

理想的には、ラッパー クラスを使用する場合、たとえばwrapper<T>、任意のタイプのオブジェクトに対して機能するようにしたいと考えていますT


はい、私が制御できるクラスの場合、コピーコンストラクターと代入演算子を次のように単純に作成できることを知っています。private

class MyClass {
public:
    // ...
private:
    MyClass( MyClass const& );
    MyClass operator=( MyClass const& );
};

コピー構築と割り当てを禁止する。std::listしかし、上記のように、たとえば、単純にコピーコンストラクターと代入演算子を作成できない場合にこれを実行したいと考えていますprivate

4

5 に答える 5

2

問題が明確になったため、これは以前の回答とは別の回答です。私の以前の回答は、正気の要件を持つ人にとって役立つかもしれないので、そのままにしておきます。

望ましい動作は不可能です: 要求は、 とまったく同じように見えるが のようにT&は動作しないものを一般的に返すことができるようにすることTです。この返されたものが実際には参照ではないという事実は、何らかの方法でユーザー (およびコンパイラー!) に知らせる必要があります。

于 2010-06-24T00:51:19.537 に答える
1

これは奇妙な要求だと思います。リストをコピーするか、参照として使用するポリシーは、通常はユーザー次第ですが、何らかの理由でリストをコピーすることが正しくない場合は、ラッパークラスがそのトリックを実行します。

ユーザーが自分のしていることを知っている場合は、浅いコピーを操作して元のコピーを変更するのではなく、リストの深いコピーを操作することの違いを理解する必要があります。ユーザーがこれを理解していない場合、彼はまだC++を使用するビジネスを持っていません。

[編集]誰かが以前にほぼ同じ解決策を投稿したことに気づきました。クラスは非常に単純にすることができます。

template <class T>
class NoncopyablePtr
{
private:
    T* ptr;

public:
    /*implicit*/ NoncopyablePtr(T* iptr): ptr(iptr) {}

    T* operator->() const
    {
        return ptr;
    }
};

これにより、ユーザーがポインティをコピーするのが非常に困難になります。彼らはoperator->を明示的に呼び出し、結果を逆参照する必要があります。ここで、NoncopyablePtr <std :: list <int >>を返すだけで、そのリストのコピーを作成するのがクライアントにとって非常に困難になります(不可能ではありませんが)。

演算子->を使用したくない場合は、ユーザーが結果を簡単にコピーできないようにする方法は他にありません。

于 2010-06-24T10:15:03.250 に答える
1

まあ、あなたはラッパーでそれを行うことができます。オーバーロードするリストのラッパーを作成します->が、実際の参照へのアクセスは決して提供しません。このような方法を回避する方法はおそらくあると思いますが、意図的に行う必要があります。本当にそうすべきではないことをクライアントに知らせるのに十分なはずです。

于 2010-06-23T23:37:24.627 に答える
1

このクラスから継承し、一致するコンストラクターを作成して親クラスのコンストラクターを呼び出し (たとえば、データを親クラスに渡すだけの同じデータ コンストラクターを使用)、コピー コンストラクターとコピー代入をプライベートにすることができます。 . または、boost::noncopyable とそのクラスの両方から派生させることもできます。その後、基本クラスへのポインター/参照を安全に使用できます。

EDIT : そのクラスにインターフェースがある場合、そのインターフェースを実装するデコレーターを作成できますが、これはコピー可能ではなく、ラッピングしているオブジェクトへの参照/ポインターを取得する方法を提供しません。

これらのどちらもオプションではない場合、保護しているクラスの適切なメソッドを呼び出す、コピー コンストラクターとコピー代入を使用せずに、まったく同じメソッドを持ち、同じように見えるクラスを作成できます (ここでも、デコレーター、難しい方法)。しかし、私はそれを避けます。

于 2010-06-23T23:38:19.623 に答える
1

これを可能にする言語はないと思います。おそらく、ポインターを返すことで、明示的なアクションを実行してコピーする必要があります。

OTOH、使用できるラッパーの例を次に示します。Uncopyable は参照ではなく値で返されることに注意してください。(しかし、おそらくポインターサイズなので、問題ありません。)

#include <iostream>
#include <list>

template <typename T>
class Uncopyable
{
public:
    Uncopyable(T& r) : ref(r) {}

    T* operator->() { return &ref; }

private:
    T& ref;
};

Uncopyable<std::list<int> > get_list()
{
    static std::list<int> l;
    l.push_back(l.size());
    return l;
}

int main() 
{
    for (int i = 0; i < 10; ++i)
    {
        Uncopyable<std::list<int> > my_l = get_list();
        std::cout << my_l->size() << std::endl;
    }
}
于 2010-06-23T23:52:55.960 に答える