0

我正在阅读 Marshall Cline 的 C++ FAQ。

目前正在使用第 10.5 点中的代码。

我有这个:

class Fred
{
public:
  Fred();
  Fred(int x, int y)
  {
    std::cout << "Fred with two ints\n" << std::endl;
  };
};

int main()
{
  std::vector<Fred>(3, Fred(4,5));
  return 0;
}

我希望看到“Fred with two ints”打印了 3 次——但它只打印了一次。为什么 - 它没有被调用 3 次?

4

2 回答 2

6

这是vector您正在调用的构造函数的签名:

vector( size_type _Count, const Type& _Val, const Allocator& _Alloc = Allocator() );

Fred(4,5)调用您定义的构造函数一次,创建的实例通过引用传递给vector<Fred>构造函数。然后,它 [创建的实例] 被复制 3 次到向量。复制操作是使用(默认)复制构造函数执行的;所以你的构造函数不会被多次调用。

于 2012-08-18T11:39:16.077 回答
2

当您编写 Fred(4,5) 时,您将调用一次用户定义的构造函数。这被传递给向量的构造函数,它将它复制 3 次到 3 个 Freds 中。这使用您的复制构造函数,而不是您的默认或自定义构造函数。如果您不编写自己的复制构造函数,则会隐式添加一个,就像赋值操作一样。下面,我添加了一个复制构造函数和赋值操作来显示幕后添加的内容:

class Fred
{
public:
  Fred();  // default constructor
  Fred(int x, int y)  // custom constructor
  {
    std::cout << "Fred with two ints\n" << std::endl;
  };
  Fred(const Fred&); // copy constructor
  Fred& operator=(const Fred&);  // assignment operator overload
};

复制构造函数:Fred(const Fred&); 当向量构造函数将您的 Fred 复制到包含的 3 个 Fred 中时,调用的是什么。如果你自己实现它,你会看到它被调用了 3 次。这是一个完整的演示:

#include <iostream>
#include <vector>
using namespace std;

class Fred
{
private:
    int x,y;

public:
    Fred()  // default constructor
    {
        cout << "Fred's default constructor\n";
    }
    Fred(int x, int y)  // custom constructor
    {
        cout << "Fred's custom constructor\n" << std::endl;
    };
    Fred(const Fred& rhs)   // copy constructor -- NOTE rhs stands for "right-hand-side"
        :x(rhs.x),y(rhs.y)
    {
        cout << "Fred's copy constructor\n";
    }
    Fred& operator=(const Fred& rhs)  // assignment operator overload
    {
        if(&rhs != this)
        { 
            cout << "Fred's assignment overload\n";
            x = rhs.x;
            y = rhs.y;
        }
        return *this;
    }
};

int main(int argc, char** argv)
{
    Fred fred;  // calls default constructor
    vector<Fred> myFreds(3,Fred(4,5));  // calls custom constructor, then copy constructor 3 times.
    fred = myFreds[0]; // calls assignment overload

    return 0;
}

输出:

Fred的默认构造函数
Fred的自定义构造函数
Fred的拷贝构造函数
Fred的拷贝构造函数
Fred的拷贝构造函数
Fred的赋值重载

如果禁用复制构造函数和赋值重载,在尝试使用它们时会出现错误。如果你使用 C++11,如果你可以通过像上面那样声明它们来禁用它们,然后是 = delete;

Fred(const Fred&) = delete;

如果您不使用 C++11,则可以通过私下声明它们来有效地禁用它们:

private:
Fred(const Fred&);  // NOTE: Don't define this function.

一旦它被禁用,你会看到你的程序不再编译,因为它试图访问被禁用的函数。它只是为您编译,因为您允许通过不自己定义它们来隐式添加它们。

于 2012-08-18T12:01:45.077 回答