繁体   English   中英

"c++构造函数和复制构造函数"

[英]c++ constructor and copy constructor

我试图了解以下代码的行为

/* code block 1 */
#include <iostream>
class A
{
        private:
            int value;

        public:
            A(int n) { std::cout << "int n " << std::endl; value = n; }
            A(const A &other) { std::cout << " other " << std::endl; value = other.value; }
            // A (A &&other) { std::cout  << "other rvalue" << std::endl; value = other.value; }

            void print(){ std::cout << "print " << value << std::endl; }

};

int main(int argc, char **argv)
{
        A a = 10;
        A b = a;
        b.print();
        return 0;
}

当我编译上面的代码时,它可以按我的预期工作

/* code block 2 */
g++ -std=c++11 t.cpp 
./a.out
int n 
 other 
print 10

当我从复制构造函数中删除const

/* code block 3 */
class A
{
        ...
        A(int n) { std::cout << "int n " << std::endl; value = n; }
        A(A &other) { std::cout << " other " << std::endl; value = other.value; }
        // A (A &&other) { std::cout  << "other rvalue" << std::endl; value = other.value; }
}

编译器不会编译

/* code block 4 */
t.cpp:19:5: error: no viable constructor copying variable of type 'A'
            A a = 10;
              ^   ~~
t.cpp:9:4: note: candidate constructor not viable: no known conversion from 'A' to 'int' for 1st argument
                    A(int n) { std::cout << "int n " << std::endl; value = n; }
                    ^
t.cpp:10:4: note: candidate constructor not viable: expects an l-value for 1st argument
                    A(A &other) { std::cout << " other " << std::endl; value = other.value; }

从结果t.cpp:9:4看来,编译器试图将 A 转换为 int,但代码是A a = 10; , 如果我是编译器,我会

  1. 试图从整数10初始化一个类型为 A 的临时变量,然后使用复制构造函数A(A &other)来初始化一个

  2. 直接用构造函数A(int)初始化a

我对t.cpp:9:4的编译器输出感到困惑

从输出t.cpp:10:4 ,编译器说它需要一个左值复制构造函数,所以我将代码更改为

/* code block 5 */
class A
{
        ...
        A(int n) { std::cout << "int n " << std::endl; value = n; }
        A(A &other) { std::cout << " other " << std::endl; value = other.value; }
        A (A &&other) { std::cout  << "other rvalue" << std::endl; value = other.value; }
}

当我按照提示定义右值复制构造函数时,输出显示未调用右值复制构造函数

/* code block 6 */
g++ -std=c++11 t.cpp 
int n 
 other 
print 10

问题:

  1. (在代码块 3 中)为什么我不能从复制构造函数中删除const
  2. (在代码块 4 -> t.cpp:9:4 中)为什么编译器会尝试从 'A' 转换为 'int'?
  3. (在代码块 5 中)编译器说它需要一个右值复制构造函数(来自代码块 4 -> t.cpp:10:4),所以我定义了一个,但运行输出显示右值复制构造函数没有被调用, 为什么?

当您的代码运行时

A a = 10;

当你写

A a = 10;

编译器将 10 转换为临时对象,然后调用复制构造函数创建一个。

A a = A(10);

考虑这个程序,

#include <iostream>
class A
{
        private:
            int value;

        public:
            A(int n) { std::cout << "int n " << std::endl; value = n; }
            A(const A &other) { std::cout << " other " << std::endl; value = other.value; }
            //A (A &&other) { std::cout  << "other lvalue" << std::endl; value = other.value; }

            void print(){ std::cout << "print " << value << std::endl; }

};

int main(int argc, char **argv)
{
        A a = 10;
        //A a(1);
        //A b = a;
        //b.print();
        return 0;
}

并编译它

g++ t.cpp -std=c++11

在运行程序时,它的输出是

int n 

现在您可能想知道为什么不调用复制构造函数A(const A &other) 这是因为 C++ 中的复制省略 编译器可以优化对复制构造函数的调用并直接调用匹配的构造函数。 所以不是A a = A(10); 被称为这个A a(10);

如果你想禁用复制省略,编译上面的程序

g++ t.cpp -std=c++11 -fno-elide-constructors

现在运行程序你可以看到下面的输出

int n 
 other 

没有复制省略。 所以, A a = A(10); 被调用。 首先创建一个临时对象,然后调用复制构造函数来创建a .

(in code block 3) why can't I remove the const from copy constructor?

因为临时对象不能绑定到左值引用。 它们只能绑定到右值引用或 const 左值引用。 A(10)创建一个临时对象,该对象只能绑定到 const 左值引用 (const A&) 或右值引用 (A&&)。

(in code block 5) the compiler says that it need a rvalue copy constructor(from code block 4 -> t.cpp:10:4), so I define one, but the running output show the rvalue copy constructor wasn't called, why?

这是由于复制省略而发生的。 -fno-elide-constructors编译它,然后你可以看到对右值构造函数的调用。 见下文。

#include <iostream>
class A
{
        private:
            int value;

        public:
            A(int n) { std::cout << "int n " << std::endl; value = n; }
            A(A &other) { std::cout << " other " << std::endl; value = other.value; }
            A (A &&other) { std::cout  << "other lvalue" << std::endl; value = other.value; }

            void print(){ std::cout << "print " << value << std::endl; }

};

int main(int argc, char **argv)
{
        A a = 10;
        //A a(1);
        //A b = a;
        //b.print();
        return 0;
}

编译:

g++ t.cpp -std=c++11 -fno-elide-constructors

输出

int n 
other lvalue

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM