【问题标题】:Return type of array subscription operator for a wrapper of type ** is *&?** 类型包装器的数组订阅运算符的返回类型是 *&?
【发布时间】:2014-02-05 21:39:05
【问题描述】:

假设我有一个类 A,它的构造函数需要一个参数 x。

class A
{
public:
    int a;
    A(int x) { a = x; std::cout << a << std::endl; }
    ~A() {}
};

现在我想分配一个 A 的数组,并将它包装在另一个类 B 中(实际上它应该是 A 的二维数组,映射到一维数组,这就是我需要包装它的原因)。由于 A 的构造函数需要参数,所以我不能使用 new[](……对吗?),所以我必须有一个 A**。另外我不想让B知道x,所以我的B是这样的:

class B
{
private:
    A** As;
    const int n;
public:
    B(int nn): n(nn) { As = new A*[n]; }
    ~B() { delete[] As; }

    A* at(int i) { return As[i]; }
    const A* at(int i) const { return As[i]; }
};

请注意,“订阅运算符”松散地表示 at() 函数。现在我的主要功能是这样的:

int main()
{
    B b(3);
    int x = -1;
    for(int i = 0; i < 3; i++)
    {
        b.at(i) = new A(x);
    }

    return 0;
}

当我用 g++ 编译它时,它会在我的“new”行打印一个错误“lvalue required as left operand of assignment”。然后我将 at() 的签名更改为

A*& at(int i)

它有效。

让我烦恼的是那个 A*&,我觉得这很奇怪……

这是我应该使用的 A*& 吗?或者任何其他处理对象数组的方法,其构造函数需要参数?顺便说一句,我们的目标机器上没有 c++11 和 boost…

【问题讨论】:

    标签: c++ arrays pointers reference wrapper


    【解决方案1】:

    “或者任何其他方式来处理对象数组,其构造函数需要参数?”

    使用std::vector,你不需要C++11,也不需要任何额外的库:

    #include <vector>
    ...
    std::vector<A> myObjects(n, A(0)); // objects will be constructed by calling A(0)
    

    您的班级B 可能如下所示:

    class B
    {
    private:
        std::vector<A> As;
        const int n;
    public:
        B(int n): n(n), As(std::vector<A>(n, A(0))) { }
        // no explicit destructor needed
        // memory management is handled by std::vector object automatically
    
        A& at(int i) { return As[i]; }
        const A& at(int i) const { return As[i]; }
    };
    

    请注意,vector 的元素存储在连续的内存块中,这些元素的生命周期与B 实例的生命周期相关联。一旦B 被破坏,向量和存储在其中的元素也会被破坏。如果n 是编译时已知的常量,您也可以考虑改用std::array

    【讨论】:

    • 如果我不需要resize我的数组,内存很紧,数组的元素被引用的非常频繁,用std::vector还合适吗?
    • @Darksair:是的,使用std::vector 的内存开销将只有几个字节(可能大约16 个)来存储它的大小和指向开始和结束的指针。元素存储在连续内存中,因此迭代元素与原始数组相同。
    • 感谢您的解释!很有帮助。我会尝试用 std::vector 重写。
    • 这也要求A(0)被复制n次?
    • @Darksair:是的,这些元素将作为A(0)的副本创建
    【解决方案2】:

    & 运算符的作用是将函数参数或返回变量更改为引用。 如果没有 & ,变量的值将被复制到一个时间变量中,因此原始变量对任何值变化都不会敏感。 通过引用处理参数将原始变量仅名称不同,但标志相同的内存块。 在此示例中,b.at(i) 语句将被复制到一个临时常量变量中,该变量在 = 语句的左侧不可用。 但是通过引用该语句的返回,它指向原始的As[i] 内存块,只有“名称”不同,因此也可以更改其值。

    【讨论】:

    • 感谢您的详细解释。我想这只是我之前从未使用过 *& ...... :)
    • 小东西。但不要忘记,当 & 是它的整个引用修饰符时, * 属于类型名称(生成指针)
    猜你喜欢
    • 2016-02-01
    • 2021-11-27
    • 2013-11-21
    • 2021-10-06
    • 1970-01-01
    • 2015-07-16
    • 1970-01-01
    相关资源
    最近更新 更多