复制构造函数和赋值运算符

发布于 2024-08-17 22:16:21 字数 1354 浏览 2 评论 0原文

我编写了以下程序来测试何时调用复制构造函数以及何时调用赋值运算符:


#include 

class Test
{
public:
    Test() :
        iItem (0)
    {
        std::cout << "This is the default ctor" << std::endl;
    }

    Test (const Test& t) :
        iItem (t.iItem)

    {
        std::cout << "This is the copy ctor" << std::endl;
    }

    ~Test()
    {
        std::cout << "This is the dtor" << std::endl;
    }

    const Test& operator=(const Test& t)
    {
        iItem = t.iItem;    
        std::cout << "This is the assignment operator" << std::endl;
        return *this;
    }

private:
    int iItem;
};

int main()
{
    {
        Test t1;
        Test t2 = t1;
    }
    {
        Test t1;
        Test t2 (t1);
    }
    {
        Test t1;
        Test t2;
        t2 = t1;
    }
}

这会产生以下输出(仅添加空行以使其更易于理解):

doronw@DW01:~$ ./test
This is the default ctor
This is the copy ctor
This is the dtor
This is the dtor

This is the default ctor
This is the copy ctor
This is the dtor
This is the dtor

This is the default ctor
This is the default ctor
This is the assignment operator
This is the dtor
This is the dtor


第二个和第三个set 的行为符合预期,但在第一个 set 中,即使使用了赋值运算符,也会调用复制构造函数。

这种行为是 C++ 标准的一部分还是只是一个聪明的编译器优化(我正在使用 gcc 4.4.1)

I wrote the following program to test when the copy constructor is called and when the assignment operator is called:


#include 

class Test
{
public:
    Test() :
        iItem (0)
    {
        std::cout << "This is the default ctor" << std::endl;
    }

    Test (const Test& t) :
        iItem (t.iItem)

    {
        std::cout << "This is the copy ctor" << std::endl;
    }

    ~Test()
    {
        std::cout << "This is the dtor" << std::endl;
    }

    const Test& operator=(const Test& t)
    {
        iItem = t.iItem;    
        std::cout << "This is the assignment operator" << std::endl;
        return *this;
    }

private:
    int iItem;
};

int main()
{
    {
        Test t1;
        Test t2 = t1;
    }
    {
        Test t1;
        Test t2 (t1);
    }
    {
        Test t1;
        Test t2;
        t2 = t1;
    }
}

This results in the following output (just added empy lines to make it more understandable):

doronw@DW01:~$ ./test
This is the default ctor
This is the copy ctor
This is the dtor
This is the dtor

This is the default ctor
This is the copy ctor
This is the dtor
This is the dtor

This is the default ctor
This is the default ctor
This is the assignment operator
This is the dtor
This is the dtor


The second and third set behave as expected, but in the first set the copy constructor is called even though the assignment operator is used.

Is this behaviour part of the C++ standard or just a clever compiler optimization (I am using gcc 4.4.1)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

喜你已久 2024-08-24 22:16:21

第一个测试用例中没有使用赋值运算符。它只是使用称为“复制初始化”的初始化形式。复制初始化在初始化对象时不考虑显式构造函数。

struct A {
  A();

  // explicit copy constructor
  explicit A(A const&);

  // explicit constructor
  explicit A(int);

  // non-explicit "converting" constructor
  A(char const*c);
};

A a;
A b = a; // fail
A b1(a); // succeeds, "direct initialization"

A c = 1; // fail, no converting constructor found
A d(1); // succeeds

A e = "hello"; // succeeds, converting constructor used

复制初始化用于与隐式转换相对应的情况,其中不显式启动转换,如函数参数传递和从函数返回。

No assignment operator is used in the first test-case. It just uses the initialization form called "copy initialization". Copy initialization does not consider explicit constructors when initializing the object.

struct A {
  A();

  // explicit copy constructor
  explicit A(A const&);

  // explicit constructor
  explicit A(int);

  // non-explicit "converting" constructor
  A(char const*c);
};

A a;
A b = a; // fail
A b1(a); // succeeds, "direct initialization"

A c = 1; // fail, no converting constructor found
A d(1); // succeeds

A e = "hello"; // succeeds, converting constructor used

Copy initialization is used in those cases that correspond to implicit conversions, where one does not explicitly kick off a conversion, as in function argument passing, and returning from a function.

迎风吟唱 2024-08-24 22:16:21

C++ 标准 8.5/12

初始化发生在
参数传递、函数返回、
抛出异常(15.1),处理
例外(15.3),以及
大括号括起来的初始值设定项列表
(8.5.1) 称为复制初始化
且等价于以下形式

T x = a;

new 中发生的初始化
表达式 (5.3.4)、static_cast
表达式 (5.2.9),函数式
符号类型转换(5.2.3),以及
基类和成员初始值设定项 (12.6.2)
称为直接初始化,并且是
相当于表格

<前><代码>T x(a);

C++ standard 8.5/12

The initialization that occurs in
argument passing, function return,
throwing an exception (15.1), handling
an exception (15.3), and
brace-enclosed initializer lists
(8.5.1) is called copy-initialization
and is equivalent to the form

T x = a;

The initialization that occurs in new
expressions (5.3.4), static_cast
expressions (5.2.9), functional
notation type conversions (5.2.3), and
base and member initializers (12.6.2)
is called direct-initialization and is
equivalent to the form

T x(a);
挖个坑埋了你 2024-08-24 22:16:21

您的第一组是根据 C++ 标准,而不是由于某些优化。

第 12.8 节 ([class.copy]) C++ 标准 给出了类似的示例:

class X {
    // ...
public:
    X(int);
    X(const X&, int = 1);
};

X a(1);     // calls X(int);
X b(a, 0);  // calls X(const X&, int);
X c = b;    // calls X(const X&, int);

最后一行将是与您的情况匹配的行。

Your first set is according to the C++ standard, and not due to some optimization.

Section 12.8 ([class.copy]) of the C++ standard gives a similar example:

class X {
    // ...
public:
    X(int);
    X(const X&, int = 1);
};

X a(1);     // calls X(int);
X b(a, 0);  // calls X(const X&, int);
X c = b;    // calls X(const X&, int);

The last line would be the one matching your case.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文