为什么这些对象是通过复制而不是通过移动返回的?

发布于 2025-01-18 17:33:19 字数 961 浏览 3 评论 0原文

为什么使用复制构造函数而不是移动构造函数返回的geta()和geta2()返回的值实例?

我正在使用Visual Studio社区2017,但是Godbolt GCC/20和在线GDB给出相同的结果。

struct A { 
    int *buff;
    A() {
        cout << "A::constructor\n";
        buff = new int[1000000];
    } 
    A(const A& a) {
        cout << "A::copy constructor\n";
        buff = new int[1000000];
        memcpy(buff, a.buff, 1000000*sizeof(int));
    }
    A(A&& original)
    {
        cout << "Move constructor" << endl;
        buff = original.buff;
        original.buff = nullptr;
    } 
    ~A() { cout << "A::destructor\n"; delete[] buff; }
};

A getA()
{
    A temp[1];
    temp[0].buff[0] = 7;
    return temp[0]; 
}

A getA2()
{
    A temp;
    A& temp2 = temp;
    temp2.buff[0] = 7;
    return temp2; // copy on return value
}
int main() {
    A copy = getA();  // calls copy instead of move
    A copy2 = getA2();  // also calls copy instead of move
}

Why are the value instances returned by getA() and getA2() returned using the copy constructor and not the move constructor?

I'm using visual studio community 2017, but godbolt gcc/20 and onlinegdb give the same results.

struct A { 
    int *buff;
    A() {
        cout << "A::constructor\n";
        buff = new int[1000000];
    } 
    A(const A& a) {
        cout << "A::copy constructor\n";
        buff = new int[1000000];
        memcpy(buff, a.buff, 1000000*sizeof(int));
    }
    A(A&& original)
    {
        cout << "Move constructor" << endl;
        buff = original.buff;
        original.buff = nullptr;
    } 
    ~A() { cout << "A::destructor\n"; delete[] buff; }
};

A getA()
{
    A temp[1];
    temp[0].buff[0] = 7;
    return temp[0]; 
}

A getA2()
{
    A temp;
    A& temp2 = temp;
    temp2.buff[0] = 7;
    return temp2; // copy on return value
}
int main() {
    A copy = getA();  // calls copy instead of move
    A copy2 = getA2();  // also calls copy instead of move
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

日久见人心 2025-01-25 17:33:19

如果目标是对语句 A copy = getA();A copy2 = getA2(); 进行移动构造,那么它可以通过使用 C++11 或 C++14 标志 -fno-elide-constructors 进行编译来完成。

演示

虽然来自 GCC

C++ 标准允许实现省略创建临时对象,该临时对象仅用于初始化相同类型的另一个对象。指定此选项会禁用该优化,并强制 G++ 在所有情况下调用复制构造函数

所以我不确定为什么在你的情况下,这个选项可以实现移动构建。这可能是一个错误,或者对我这边正在发生的事情的概念缺乏理解。因此,如果/需要时我会删除这个答案(一旦我知道为什么会发生这种情况)。

我无法将其放入评论中,因此在此发布作为答案。

If the aim is to do move construction for the statements A copy = getA(); and A copy2 = getA2(); then it can be done by compiling with the flag -fno-elide-constructors with C++11 or C++14.

Demo.

Although from GCC

The C++ standard allows an implementation to omit creating a temporary which is only used to initialize another object of the same type. Specifying this option disables that optimization, and forces G++ to call the copy constructor in all cases.

So i am not sure why in your case, this options enables move construction. This maybe a bug or lack of understanding of the concept about what is going on here from my side. And so i will delete this answer if/when required(once i know why is this happening).

I couldn't fit this into a comment so posting here as an answer.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文