C++ 缺少对象的构造和销毁

c++ missing construction and destruction of an object

提问人:Asif Shaikh 提问时间:5/22/2022 最后编辑:Jerry CoffinAsif Shaikh 更新时间:5/22/2022 访问量:89

问:

以下代码:

#include <iostream> 
#include <string>
using namespace std;
void print(string a) { cout << a << endl; }
void print(string a, string b) { cout << a << b << endl; }
 
class A {
    public:
    string p;
    A() { print("default constructor"); }   
    A(string a){ p = a; print("string constructor ", p); }
    A(const A& o) { print("copy constructor"); }
    A (A&& o) { print("move constructor"); }
    A& operator=(const A& o) { print("copy assignment"); return *this; }
    A& operator=(const A&& o) { cout << "move assignment to:" << p << " from:" << o.p << endl; return *this; }
    ~A() { print("destructor ", p); }
};

A operator+(const A& a, const A& b) { 
    cout << "add" <<endl; 
    A c("f"); 
    return c;
}
    
A f(A& a, A& b, A& c) {
    A d("e");
    d = a+b+c;
    print("after add");
    return d;
}

int main() {
    A a("a"); A b("b"); A c("c");
    A whereDidThisGo {f(a,b,c)};
    print("end");
}

具有以下输出:

string constructor a
string constructor b
string constructor c
string constructor e
add
string constructor f
add
string constructor f
move assignment to:e from:f
destructor f
destructor f
after add
end
destructor e
destructor c
destructor b
destructor a

进程在 0.06744 秒后退出,返回值为 0
按任意键继续 . . .

main中定义的whereDidThisGo变量的构造/销毁在哪里?

C++ 析构函数 复制 构造函数

评论

1赞 HolyBlackCat 5/22/2022
查找“NRVO”。此外,移动赋值应使用非常量参考参数。
1赞 Jerry Coffin 5/22/2022
@HolyBlackCat是对的。尽管常量右值引用是可能的,但它几乎总是一个错误。采用右值引用的意义通常是要修改它所指的内容。

答:

1赞 Asif Shaikh 5/22/2022 #1

关于 NRVO 的 TIL,对于像我这样试图学习构造函数的人来说,这不是一个好的优化哈哈。

谢谢你的回答,是的,移动分配应该是一个非常量指针,我只是忽略了它。

评论

0赞 user12002570 5/22/2022
您可以通过向编译器提供 来禁用此优化。请参阅下面回答中的示例(演示链接)。-fno-elide-constructors
0赞 quetzalcoatl 5/22/2022
我怀疑 HolyBlackCat 和 JerryCoffin 会写答案,因为他们在评论中回复了,所以请将其中一个答案标记为“已接受”,以便整个问题标记为完成。“Anoop Rana”看起来不错,因为它提到了 NRVO 的处理方式——但这可能是特定于编译器的。
2赞 user12002570 5/22/2022 #2

main中定义的whereDidThisGo变量的构造/销毁在哪里?

由于命名的返回值优化(又名 NRVO),您看不到此结果。

对于像我这样试图学习构造函数的人来说,这不是一个好的优化

您可以通过向编译器提供标志来禁用此 NRVO。演示-fno-elide-constructors


另外,请注意,在您的示例中,应改为:A::operator=(const A&&)

//-----------vv------->no need for const  here
A::operator=(A&&)