首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >当类型合适的构造函数可用时,为什么有一个编译器试图使用删除的复制构造函数

当类型合适的构造函数可用时,为什么有一个编译器试图使用删除的复制构造函数
EN

Stack Overflow用户
提问于 2018-09-12 06:35:51
回答 1查看 150关注 0票数 0

我有一个模板类属性,它包装了其他类型:

template <typename T>
class Property
{
private:
    T value;
public:
    Property() = default;

    Property(const T& initialValue)
    : value(initialValue) {}
    virtual ~Property() = default;

    //Make this class non-copyable.
    Property(const Property&) = delete;
    Property& operator=(const Property&) = delete;

    virtual Property& operator=(const T& other)
    {
        value = other;
        return *this;
    }

    //... a bunch of other unimportant stuff
}

Visual Studio 15.7.6和其他一些编译器对此非常满意

{ //function or class definition (default member initialization)    
    Property<int> prop = 5;
}

然而,(针对专有编译目标稍作修改)以上声明,GCC 4.9.4失败:

Error GD4849D22 use of deleted function 
'Property<T>::Property(const Property<T>&) [with T = int]' 

编译器似乎正在尝试构造一个RValue属性,然后使用已删除的复制构造函数,而不是简单地使用类型适当的构造函数。

这是GCC过于谨慎的表现吗?

Property<int> prop(5); //explicit constructor call - valid with GCC Compiler

Property<int> myOtherProp;
myOtherProp = 5; //Also fine (obviously)

或者,这是一个MSVC玩得不定,做一些标准说它不应该或没有必要做的事情的情况?

不幸的是,我不能更新我的GCC版本。因为存在变通方法,所以我更多地是在寻找“为什么”会发生这种情况。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-09-12 06:56:27

我相信这里发生的事情是guaranteed copy elision在工作(这是C++17的一个特性)。像这样的成员声明

struct A
{
    Property<int> prop = 5;
};

表示成员将通过复制初始化进行初始化。首先,使用转换构造函数从5构造一个临时的Property对象,然后从该对象构造实际的属性。由于Property不可移动,因此将调用复制构造函数,该构造函数将被删除。虽然编译器甚至在C++17之前就被允许elide this copy (任何合理的编译器,因为基本上永远都会这样做),但它仍然需要强制执行所有约束,例如任何必要的构造函数的存在和可访问性,就像制作了副本一样。C++17取消了所有这些,基本上是强制复制省略。

在这里使用clang进行快速测试(https://godbolt.org/#g:!((g:!((g:!((g:!((h:codeEditor,i:(j:1,lang:c%2B%2B,source:'%0Atemplate+%3Ctypename+T%3E%0Aclass+Property%0A%7B%0Aprivate:%0A++++T+value%3B%0Apublic:%0A++++Property(%29+%3D+default%3B%0A%0A++++Property(const+T%26+initialValue%29%0A++++:+value(initialValue%29+%7B%7D%0A++++virtual+~Property(%29+%3D+default%3B%0A%0A++++//Make+this+class+non-copyable.%0A++++Property(const+Property%26%29+%3D+delete%3B%0A++++Property%26+operator%3D(const+Property%26%29+%3D+delete%3B%0A%0A++++virtual+Property%26+operator%3D(const+T%26+other%29%0A++++%7B%0A++++++++value+%3D+other%3B%0A++++++++return+*this%3B%0A++++%7D%0A%0A++++//...+a+bunch+of+other+unimportant+stuff%0A%7D%3B%0A%0A%0Astruct+A%0A%7B+//function+or+class+definition+(default+member+initialization%29++++%0A++++Property%3Cint%3E+prop+%3D+5%3B%0A%7D%3B%0A'%29,l:'5',n:'0',o:'C%2B%2B+source+%231',t:'0'%29%29,k:50,l:'4',n:'0',o:'',s:0,t:'0'%29,(g:!((h:compiler,i:(compiler:clang_trunk,filters:(b:'0',binary:'1',commentOnly:'0',demangle:'0',directives:'0',execute:'1',intel:'0',trim:'1'%29,lang:c%2B%2B,libs:!(%29,options:'-std%3Dc%2B%2B14',source:1%29,l:'5',n:'0',o:'x86-64+clang+(trunk%29+(Editor+%231,+Compiler+%231%29+C%2B%2B',t:'0'%29%29,k:50,l:'4',n:'0',o:'',s:0,t:'0'%29%29,l:'2',m:65.36731634182908,n:'0',o:'',t:'0'%29,(g:!((h:output,i:(compiler:1,editor:1,wrap:'1'%29,l:'5',n:'0',o:'%231+with+x86-64+clang+(trunk%29',t:'0'%29%29,header:(%29,l:'4',m:34.63268365817092,n:'0',o:'',s:0,t:'0'%29%29,l:'3',n:'0',o:'',t:'0'%29%29,version:4);如果您将语言标准切换到c++17,您将看到它突然可以在…中工作

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52285048

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档