这是隐式调用复制构造函数吗?

时间:2014-03-04 17:05:30

标签: c++ reference copy-constructor

我有以下课程:

class Player
{
public:
    Inventory& GetInventory()
    {
        return inventory;
    }
private:
    Inventory inventory;
};

class Inventory
{
    // Methods removed for brevity
private:
    std::vector<std::string> items;
};

我要做的是允许代码的用户修改Player::inventory的内容,而无法将其重新分配给其他对象。简短的例子:

Player player;

// OK: I want to able to add items.
player.GetInventory().AddItem("Item 1");

// Not OK: I don't want to be able to assign
// Player::inventory to a different Inventory.
Inventory badInventory;
player.GetInventory() = badInventory;

我知道我可以通过修改GetInventory()来返回Inventory* const来实现这一目标,但这种情况让我怀疑我认为引用的真实性。我相信他们:

  1. 不是对象本身,所以没有地址。
  2. 在他们的一生中不能重新分配。
  3. 申报时必须初始化。
  4. 我告诉我badInventory必须以某种方式被隐含地复制。所以我定义了一个复制构造函数,希望记录调用,如下所示:

    Inventory(const Inventory& rhs)
    {
        std::cout << "Copy ctor." << std::endl;
    }
    

    但这永远不会激发。所以我的问题归结为:这条线上发生了什么?

    player.GetInventory() = badInventory;
    

    我在这里遗漏了一些东西,但我不知道它是什么。

3 个答案:

答案 0 :(得分:6)

该行实际上是调用复制赋值运算符,而不是复制构造函数。这是声明为

的函数
Inventory& operator=(const Inventory&);

请注意,player.GetInventory()已存在的对象,因此无法调用复制构造函数,因为您没有构建任何内容。

如果您想禁止复制库存,请删除以下功能:

Inventory(const Inventory&) = delete;
Inventory& operator=(const Inventory&) = delete;

或者,如果您的编译器缺少C ++ 11支持,请将它们声明为private并且不提供定义。

private:
    Inventory(const Inventory&);
    Inventory& operator=(const Inventory&);

答案 1 :(得分:1)

在这个场景中

player.GetInventory() = badInventory;

使用类库存的复制赋值运算符。

您可以将复制/移动分配运算符定义为已删除。例如

class Inventory
{
public:
    Inventory & operator =( const Inventory & ) = delete;
    Inventory & operator =( Inventory && ) = delete;
    // Methods removed for brevity
private:
    std::vector<std::string> items;
};

或者您可以将它们声明为私有成员函数。

虽然在我看来,如果你定义处理矢量作为成员函数的所有必需方法而不是返回对向量的引用会更好

答案 2 :(得分:0)

此链接可能有助于理解特殊成员函数(在这种情况下复制构造函数和复制赋值): http://www.cplusplus.com/doc/tutorial/classes2/