0

What do i need to do to the following code in order for it to output the values of A and B? You can edit and compile it here if you like.

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} )完成时被释放。

有三种方法可以解决这个问题:

  1. 如果您知道SomeClass对象的生命周期,则可以将副本复制到SomeClass实例之外的向量f。例如,如果f仅在创建它的函数的持续时间内存在,您可以执行类似的操作

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

    创建函数“拥有” aVector,并f对其有引用。

  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在创建向量时会创建一个副本,并且该副本将保留 value 1

在情况 (2) 和 (3) 中,为了能够通过更新来更新向量A,您必须将指针存储在向量中,如前所述。您也可以在情况 (1) 中执行此操作。请注意,在存储指针时,您需要确保它们指向的内存在您可以使用指针时一直存在——本质上与使用向量本身解决的所有权问题相同。

在情况 (1) 中,您还可以通过更新 来更新向量的内容aVector[0],因为f有对 的引用aVector

于 2013-06-28T12:32:48.303 回答
1

我会说使用指针,并在你的类中持有一个真实的向量而不是一个引用

#include <iostream>
#include <vector>

int main()
{
//This is now a vector type, not a reference to vector. Also, it contains
// pointer to int instead of a copy.
typedef const std::vector<int *> t; 

class SomeClass
{
    t data;
public:

// We pass the vector by reference here.

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

int A = 1;
int B = 2;

// We have to pass the address of A and B here.
SomeClass f = SomeClass( {&A, &B} );
f.disp();

A = 456;
f.disp();
}

然而,由于我们持有 A 和 B 上的指针(它们是局部变量),一旦 A 和 B 被丢弃(基本上是下一个 '}'),向量将持有指向无效值的指针,这很糟糕。

在您的示例中,您的类与 A 和 B 一起被丢弃,所以没关系,但是如果您的类比 A 和 B 存活的时间更长,则 disp() 的行为将是未定义的(可能是 SIGSEGV)。

于 2013-06-28T12:00:34.997 回答
0

有三个错误。

  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

您需要一个更永久的向量才能使您的示例正常工作。

您所说的类是可以的,但必须记录自己以存储传递的引用,因此 REQUIRE 参数具有对 SomeClass 实例的生命周期的爱。

您当前的调用在那里失败:您传入一个临时创建的向量,并在该行的末尾被销毁。当你进入下一行时,你的 f 持有一个悬空引用,使用它会让你进入未定义的行为领域。

在单独的行中修复 vreate 向量并将其传递给 SomeClass ctor。

于 2013-06-28T11:59:34.993 回答
0

目前,您在类中持有对临时对象的引用,并且取消引用它会触发未定义的行为。您需要将 typedef 更改为 vector(remove &) 并在构造函数中添加: SomeClass(t& _data) 以便在类中保留一个实际对象并接受构造函数参数作为参考

于 2013-06-28T11:54:11.520 回答