【发布时间】:2022-07-04 12:48:28
【问题描述】:
当您从函数(按值传递)返回类的对象(不是特定的类)时,我很难理解会发生什么 在这段代码中: 示例 1
#include<iostream>
#include<vector>
#include<string>
using namespace std;
class test {
public:
test(int y) {
printf(" test(int y)\n");
}
test() {
printf(" test()\n");
}
test( const test& z) {
printf(" test( const test&z)\n");
}
test(test&& s)noexcept{
printf(" test(test&& s)\n");
}
test& operator=(test e) {
printf(" test& operator=( test e)\n");
return *this;
}
};
test Some_thing() {
test i;
return i;
}
int main()
{
Some_thing();
return 0;
}
输出:
test()
test(test&& s)
前面的输出让我明白了在函数 (Some_thing()) 的作用域中创建了两个对象。第一个是一个左值对象,我们在函数的第一行( Some_thing ( ) )中创建它并给它一个名称( i )所以构造函数test ( ) 被调用。
而第二个是右值对象所以调用了构造函数test ( test&& s )。
但是当我删除了这个构造函数test(test&& s)noexcept并改变了这个构造函数
test( const test& z)
进入
test( test& z)
然后再次运行代码:
示例 2
#include<iostream>
#include<vector>
#include<string>
using namespace std;
class test {
public:
test(int y) {
printf(" test(int y)\n");
}
test() {
printf(" test()\n");
}
test( test& z) {
printf(" test( test&z)\n");
}
test& operator=(test e) {
printf(" test& operator=( test e)\n");
return *this;
}
};
test Some_thing() {
test i;
return i;
}
int main()
{
Some_thing();
return 0;
}
输出:
test()
test( test&z)
虽然我预计这段代码不会编译,因为没有构造函数将test&& 或const test& 作为参数
当我尝试在前面的代码中添加一行时,test(test&& z) = delete
示例 3
#include<iostream>
#include<vector>
#include<string>
using namespace std;
class test {
public:
test(test&& z) = delete;
test(int y) {
printf(" test(int y)\n");
}
test() {
printf(" test()\n");
}
test( const test& z) {
printf(" test( test&z)\n");
}
test& operator=(test e) {
printf(" test& operator=( test e)\n");
return *this;
}
};
test Some_thing() {
test i;
return i;
}
int main()
{
Some_thing();
return 0;
}
我试图编译它,但它没有编译,也没有运行
那么EXAMPLE 2是如何编译运行的??????以及如何使用构造函数test( test&z) 而不是
test(test&& z)??????
(我的意思是test( test&z)不是test( const test&z)所以不能用test( test&z)代替test(test&& z))
编辑: 此代码编译并运行: 示例 4
#include<iostream>
#include<vector>
#include<string>
using namespace std;
class test {
public:
test(test&& z) = delete;
test(int y) {
printf(" test(int y)\n");
}
test() {
printf(" test()\n");
}
test(const test& z) {
printf(" test( test&z)\n");
}
test& operator=(test e) {
printf(" test& operator=( test e)\n");
return *this;
}
};
int main()
{
test u;
test r(u);
return 0;
}
输出:
test()
test( test&z)
【问题讨论】:
-
对象切片发生。永远不要这样做。
-
什么是对象切片??????在我的例子中什么时候发生???? @user207421
-
视情况而定。在较早的 C++ 标准(C++17 之前)中,按值返回的语义是将副本返回给调用者。但是,这些标准也明确允许(但不要求)编译器在某些情况下删除(省略)对象的副本(例如,如果检查副本的唯一方法是通过跟踪调用构造函数和析构函数)和一些编译器(具有相关的优化设置)实现了返回值优化以在某些情况下删除副本,而有些则没有。从 C++17 开始,复制省略在多种情况下成为强制要求。
-
@user207421 对象切片是如何发生的?这里没有继承。
-
我认为示例 2 的关键误解是您认为复制构造函数必须使用
const,但事实并非如此。 C++ 标准的“class.copy”部分明确指出像test(test&)这样的构造函数是复制构造函数。
标签: c++