提问人:mdf 提问时间:1/13/2022 更新时间:1/13/2022 访问量:96
没有析构函数的类返回对象的副本,但是当我添加析构函数时,它会返回相同的对象
Class with no destructor returns copy of object but when I add a destructor it returns the same object
问:
我正在玩C++中的类,特别是实现一个带有返回对象的静态“create”函数的私有构造函数。
// main.cpp
#include <iostream>
class Foo {
public:
static Foo create_foo() {
Foo foo{};
std::cout << "Foo::create_foo():: Address of foo: " << &foo << std::endl;
return foo;
}
private:
Foo() { std::cout << "Foo::Foo():: Constructor" << std::endl; }
};
int main() {
auto foo = Foo::create_foo();
std::cout << "main():: Address of foo: " << &foo << std::endl;
return 0;
}
运行上面的代码会创建两个不同的对象:一个 in 和一个 in,如输出所示:Foo
Foo::create_foo()
main()
Foo::Foo():: Constructor
Foo::create_foo():: Address of foo: 0x7ffe5d5e60bf
main():: Address of foo: 0x7ffe5d5e60ef
我的第一个倾向是“好吧,它调用了复制构造函数。因此,我添加了以下公共复制构造函数:
Foo(Foo const&) { std::cout << "Foo::Foo(Foo const&):: Copy constructor" << std::endl; }
这就是我的困惑所在,只需添加一个复制构造函数,现在包含相同的对象:Foo::create_foo()
main()
Foo::Foo():: Constructor
Foo::create_foo():: Address of foo: 0x7ffe53c9d63f
main():: Address of foo: 0x7ffe53c9d63f
如果我添加一个公共析构函数,也会发生同样的行为:
~Foo() { std::cout << "Foo::~Foo():: Destructor" << std::endl; }
输出:
Foo::Foo():: Constructor
Foo::create_foo():: Address of foo: 0x7ffed84a400f
main():: Address of foo: 0x7ffed84a400f
Foo::~Foo():: Destructor
我只是好奇为什么添加额外的(复制)构造函数或析构函数会改变我的静态函数的行为。可能是一些编译器优化吗?我正在使用和编译没有任何标志()。gcc version 10.2.1 20201125 (Red Hat 10.2.1-9) (GCC)
g++ -o main main.cpp
答:
1赞
user17732522
1/13/2022
#1
编译器允许省略代码中所有潜在的副本/移动。从 C++17 开始,这甚至是强制性的,除了 from 的返回值的移动构造。Foo
create_foo
foo
后一种情况称为命名返回值优化,它仍然是一种可选优化,编译器可以选择应用并省略构造函数调用。
您未在启用优化的情况下进行编译。添加标志,NRVO 将应用于您描述的所有情况。-O2
我不知道为什么 GCC 只有在添加特殊成员函数时才会在没有优化标志的情况下应用 NRVO,但同样令人惊讶的是,它完全没有优化标志就应用了 NRVO。
应用 NRVO 后(以及所有其他省略项也应用,无论是否强制),将只有一个对象,由 into in 直接构造。Foo
create_foo
foo
main
评论
int data[50];
auto foo = Foo::create_foo();