简体   繁体   English

gcc 4.8.2在此默认默认构造函数中调用复制构造函数时是否正确?

[英]Is gcc 4.8.2 correct in invoking the copy constructor in this defaulted default constructor?

Here's a simple, self-contained, non-compilable-on-gcc-4.8.2 example of what I'm trying to accomplish: 这是我要完成的一个简单的,自包含的,不可编译的gcc-4.8.2示例:

#include <atomic>

template <typename T>
class ValueParameter
{
public:
    ValueParameter() = default;

    ValueParameter(T initialValue) :
        _val(initialValue)
    {
    }

private:
    std::atomic<T> _val{T()};
};

ValueParameter<int> x;

I've compiled this successfully on several other gcc versions, including 5.3, but gcc 4.8.2 fails with the following error: 我已经在其他几个gcc版本(包括5.3)上成功编译了此代码,但gcc 4.8.2失败并出现以下错误:

/tmp/gcc-explorer-compiler11658-82-1cqz6ui/example.cpp: In constructor 'ValueParameter<T>::ValueParameter() [with T = int]':
7 : error: use of deleted function 'std::atomic<int>::atomic(const std::atomic<int>&)'
ValueParameter() = default;
^
In file included from /tmp/gcc-explorer-compiler11658-82-1cqz6ui/example.cpp:1:0:

You can see the results online here . 您可以在此处在线查看结果

I understand that std::atomic<T> is non-copyable, but it doesn't make any sense to me why the compiler would be trying to use the copy constructor within the default constructor. 我知道std::atomic<T>是不可复制的,但是对我而言,编译器为何要尝试在默认构造函数中使用copy构造函数没有任何意义。 I did discover that changing the line: 我确实发现改变了这一行:

    std::atomic<T> _val{T()};

to

    std::atomic<T> _val;

makes the file compile successfully. 使文件成功编译。 The uniform initialization was a relic from a previous version of the class that didn't have the constructor taking an initial value. 统一初始化是该类先前版本的遗物,该早期版本的构造函数没有采用初始值。

Should this be an error? 这应该是一个错误吗? Furthermore, what behavior should I expect in this case, where the member is initialized both inline to the class and within a constructor initializer list? 此外,在这种情况下,成员被内联到类并在构造函数初始化器列表中被初始化,我应该期待什么行为? I would like the default constructor to initialize val to T() , so I think I need the brace initializer there. 我想要默认的构造函数将val初始化为T() ,所以我认为我需要在这里进行括号初始化。

This is definitely a gcc bug, and one that they've fixed by 4.9. 这绝对是gcc的错误,并且已由4.9修复。 At no point is your code invoking the copy constructor of ValueParameter<T> - so that member function should not be instantiated. 您的代码绝对不会调用ValueParameter<T>的副本构造函数-这样就不应实例化成员函数。 Using a default member initializer for atomic<T> is fine - it is, indeed, constructible from a T . 使用atomic<T>的默认成员初始化器很好-实际上,可以从T构造它。

Furthermore, what behavior should I expect in this case, where the member is initialized both inline to the class and within a constructor initializer list? 此外,在这种情况下,成员被内联到类并在构造函数初始化器列表中被初始化,我应该期待什么行为?

Default member initializers are just that - defaults. 默认成员初始化程序就是这样-默认值。 If you provided an initializer in the mem-initializer-list (as you do in the ValueParameter(T ) constructor), then the default is ignored. 如果您在mem-initializer-list中提供了一个初始化程序(就像在ValueParameter(T )构造函数中所做的ValueParameter(T ) ),则默认值将被忽略。 If you do not provide such an initializer (as you don't in ValueParameter() ), then the default is used. 如果您不提供这样的初始化程序(因为您不在ValueParameter() ),那么将使用默认值。

I would like the default constructor to initialize val to T() , so I think I need the brace initializer there. 我想要默认的构造函数将val初始化为T() ,所以我认为我需要在这里进行括号初始化。

Your code should do precisely what you want it to do. 您的代码应该精确地完成您想要的工作。 gcc 4.8 just has a bug here. gcc 4.8这里有一个bug。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM