0

と の値を出力するには、次のコードに何をする必要がAありBますか? 必要に応じて、ここで編集してコンパイルできます。

typedef const std::vector<int>& t;

class SomeClass
{
    t data;
public:
    SomeClass(t _data) : data(_data) {}
    void disp()
    {
        for (auto v : data)
            std::cout << v << ", ";
        std::cout << std::endl;
    }        
};

int A = 1;
int B = 2;

SomeClass f = SomeClass( {A, B} );
f.disp();

A = 456;
f.disp();
4

5 に答える 5

2

あなたのコードに基づいて、クラスの外部からベクトルの要素を更新できるようにしたいようです。

ただし、これに到達する前に、一時オブジェクトへの参照を格納しているという問題があります ( でvector構成されています{1, 2})。このオブジェクトは、呼び出しがSomeClass( {A, B} )完了すると割り当てが解除されます。

これを解決するには、次の 3 つの方法があります。

  1. オブジェクトの存続期間がわかっている場合は、インスタンスSomeClassの外部でベクターにコピーできます。たとえば、それを作成した関数の期間だけ存在する場合は、次のようなことができますSomeClassff

    std::vector<int>   aVector({A, B});
    SomeClass          f = SomeClass(aVector);
    

    作成関数は「所有」しaVectorfそれへの参照を持っています。

  2. SomeClassインスタンスにベクターのコピーを作成させることができます。このために、参照によってベクトルを渡すことができますが、コンストラクターでコピーを作成します。

    class SomeClass
    {
        std::vector<int>    data;
      public:
        SomeClass(const std::vector<int> &_data) : data(_data) {}
        ...
    }
    

    f現在、ベクターの独自のコピーを「所有」しています。ただし、オブジェクトの外部から要素の値を変更することはできなくなります。そのため、オプションである場合は、ポインターをベクター ( std::vector<int*>) 内に格納するか、コンテンツを変更するためのメソッドをクラスに提供する必要があります。

  3. 移動セマンティクス (C++11) を使用して、引数ベクトルの内部ストレージがコピーされず、SomeClass::data構築中に再割り当てされるようにすることができます。

    class SomeClass
    {
        std::vector<int>    data;
      public:
        SomeClass(std::vector<int> &&_data) : data(std::move(_data)) {}
        ...
    }
    

    前と同じように、fベクトルを「所有」します。繰り返しf.dataますが、オブジェクトの外部から の内容を変更することはできないため、ベクトルにポインターを格納するか、メソッドを提供する必要があります。

これらのケースのいずれにおいても、上に書かれているように、更新によってベクトルの内容を変更することはできませんA。これはA、ベクトルの作成時に のコピーが作成され、そのコピーが値を保持するためです1

(2) と (3) の場合、 update によってベクトルを更新できるようにするにはA、前述のようにベクトルにポインターを格納する必要があります。(1)の場合も同様です。ポインターを格納するときは、ポインターを使用している限り、ポインターが指しているメモリが持続することを確認する必要があることに注意してください。基本的に、ベクター自体で解決するのと同じ所有権の問題です。

(1) の場合、は への参照を持っているaVector[0]ため、を更新することでベクトルの内容を更新することもできます。faVector

于 2013-06-28T12:32:48.303 に答える
0

間違いは3つ。

  1. 初期化リストではありません。
  2. f は期待どおりに割り当てられていません。
  3. データには値のアドレスがありません

そう:

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

using namespace std;
typedef const std::vector<int*>& t;

class SomeClass
{
    t data;
public:
    SomeClass(t& _data) : data(_data) {}
    void disp()
    {
        for (auto v : data)
            std::cout << *v << ", ";
        std::cout << std::endl;
    }        
};

int
main(int argc, char* argv[]) {
    int A = 1;
    int B = 2;
    t v = {&A, &B};

    SomeClass f(v);
    f.disp();

    A = 456;
    f.disp();
    return 0;
}
于 2013-06-28T12:02:18.277 に答える
0

例が機能するには、より永続的なベクトルが必要です。

あなたが言ったクラスは問題ありませんが、渡された参照を保存するためにそれ自体を文書化する必要があるため、 SomeClass インスタンスの生涯にわたる愛を持つ REQUIRE 引数が必要です。

現在の呼び出しはそこで失敗します。一時的に作成され、その行の最後で破棄されるベクトルを渡します。次の行に到達すると、 f はダングリング参照を保持し、それを使用すると未定義の動作が発生します。

修正するには、ベクトルを別の行に作成し、それを SomeClass ctor に渡します。

于 2013-06-28T11:59:34.993 に答える