复制省略可见的副作用 [英] copy elision visible side effect

查看:85
本文介绍了复制省略可见的副作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下代码:

  #include< iostream> 

使用命名空间std;

结构Foo {
public:
int _a {};
Foo(int a):_a {a}
{
std :: cout<< ctor<< std :: endl;
}

Foo(const Foo&)
{
std :: cout<< 复制<< std :: endl;
}
};

int main(){
Foo a {10};
Foo b = 10;
std :: cout<< b._a<< std :: endl;
}

当我使用



进行编译时


g ++ -std = c ++ 11 -fno-elide-constructors test.cpp


输出为


ctor
ctor
复制
0


这是我期望的,因为在 Foo b = 10 10 是从 int 隐式构造的,然后 b 是从 Foo构造的副本。此外,我的副本构造函数不执行任何操作,因此成员 _a 保持为 0 (因为它在类中) -初始化)。



但是,当我使用复制省略


g ++- std = c ++ 11 test.cpp


输出为


ctor
ctor
10


这是令人惊讶的至少可以说。我知道这里没有复制构造函数,但这是一个严重的副作用(事实上,该成员曾经被初始化为0,然后被初始化为10),因为它会影响其余的代码路径。



这种行为正常吗?

解决方案

单点的全部在特定情况下,将复制省略作为一种优化是为了消除复制构造的副作用。也就是说,是的,尽管复制构造函数和/或析构函数具有副作用,但它仍希望复制省略发生。



如果您不希望在在某些情况下,您需要安排将其禁止。在您的特定情况下,禁止复制清除确实有点烦人,但类似的方法应该可以解决问题:类型名T>
T const&禁止(T const& ref){
return ref;
}
// ...
Foo b =抑制< Foo>(10);


Consider this code:

#include <iostream>

using namespace std;

struct Foo {
public:
    int _a{};
    Foo(int a) : _a{a} 
    {
        std::cout << "ctor" << std::endl;
    }

    Foo(const Foo &)
    {
        std::cout << "copy" << std::endl;
    }
};

int main () {
    Foo a{10};
    Foo b = 10;
    std::cout << b._a << std::endl;
}

When I compile with

g++ -std=c++11 -fno-elide-constructors test.cpp

the output is

ctor ctor copy 0

which is what I expect, since the in Foo b = 10, 10 is implicitly constructed from int, then b is copy constructed from Foo. Furthermore, my copy constructor doesn't do anything, so the member _a remains 0 (as it is in-class-initialized).

However, when I use copy elision

g++ -std=c++11 test.cpp

the output is

ctor ctor 10

which is surprising to say the least. I understand that the copy constructor is elided here, but this is a serious side-effect (the fact that the member is once initialized to 0 and once to 10), as it affects the rest of the code path.

Is this behaviour normal?

解决方案

The whole point of singling copy elision out as a on optimization in specific cases is to allow eliding side effects of copy construction. That is, yes, it expected that copy elision happens despite the copy constructor and/or the destructor having side effects.

If you don't want copy elision to happen in certain cases you'll need to arrange for it to be inhibited. In your specific case it is admittedly a bit annoying to inhibit copy elision but something like this should do the trick:

template <typename T>
T const& inhibit(T const& ref) {
    return ref;
}
// ...
Foo b = inhibit<Foo>(10);

这篇关于复制省略可见的副作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆