关于复制构造函数的疑问
Closed this issue · 2 comments
MKamaitachi commented
你好。我在看你的“谷雨同学的C++教程”时,在看到第五章的复制构造函数部分时,遇到一个复制构造函数调用的问题,下面是的代码:
#include <iostream>
#include <cstring>
struct String {
char* str;
unsigned len;
String(unsigned num, char c){
len = num;
str = new char[num + 1];
unsigned i{0};
for(i;i < num;i++)
str[i] = c;
str[i + 1] = '\0';
}
String(const char* strVa){
len = std::strlen(strVa);
unsigned i{0};
str = new char[len + 1];
for(i;i < len;i++)
str[i] = strVa[i];
str[i + 1] = '\0';
}
String(){
len = 0;
str = new char[1]{'\0'};
}
String(const String& s){
std::cout << "Copy func structor" << std::endl;
}
};
class S{
public:
S(){
std::cout << "func structor" << std::endl;
}
S(const S& s){
std::cout << "Copy func structor" <<std::endl;
}
};
void f(String d){
std::cout << "f" << std::endl;
}
void f(S s){}
String g(void){
String sth("hello");
return sth;
}
S h(void){
S e;
return e;
}
int main(){
String a;
String b(3,'o');
String c("Hello");
S e;
a = g(); //此处调用了复制构造函数
f(c); //struct中声明的复制构造函数,在此处f没有调用复制构造函数,
std::cout << "endl" << std::endl;
e = h(); //此处没有调用复制构造函数
f(e); //class中声明的复制构造函数,在此处f调用了额复制构造函数。
}
我分别创建了String结构体和S类,我按照教程创建了两个函数来实现复制构造,然而我发现T g(void){}
函数在返回的对象是结构体创建时会调用复制构造函数,若返回的对象时类创建的则不会,同样,void f(T t){}
函数在调用时传入的对象是结构体创建的则不会调用复制构造函数,反之,若是类创建的则会调用构造函数。此处是否教程有问题?
注:编译器使用的是GCC,C++14。
guyutongxue commented
你刚刚好看错了。
a = g();
没有调用复制构造函数,因为有复制消除(NRVO)。你观察到的“调用复制构造函数”,恰恰是下一行的 f(c);
。
e = h();
同理,因为 NRVO 没有调用复制构造函数。你观察到的调用,确实是下一行的 f(e);
。
你可以删除两条赋值,你仍然会观察到同样的输出结果,这证明了调用复制构造与否,与如何声明类是无关的。
MKamaitachi commented
你刚刚好看错了。
a = g();
没有调用复制构造函数,因为有复制消除(NRVO)。你观察到的“调用复制构造函数”,恰恰是下一行的f(c);
。
e = h();
同理,因为 NRVO 没有调用复制构造函数。你观察到的调用,确实是下一行的f(e);
。你可以删除两条赋值,你仍然会观察到同样的输出结果,这证明了调用复制构造与否,与如何声明类是无关的。
谢谢,我删除两条复制后进行测试,确实如你所说结果一样。现在也理解了,感谢解答!