首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >只移动继承构造函数中的类参数

只移动继承构造函数中的类参数
EN

Stack Overflow用户
提问于 2016-05-06 05:34:44
回答 1查看 206关注 0票数 4

下面的代码不编译GCC 6.1,而是在Clang 3.8.0Visual Studio 2015中工作

代码语言:javascript
运行
复制
#include <memory>

class base {
public:
    base(std::unique_ptr<int>) {}
};

class derived : public base {
public:
    using base::base;
};

int main() {
    derived df(std::make_unique<int>());
}

有以下错误:

代码语言:javascript
运行
复制
main.cpp: In constructor 'derived::derived(std::unique_ptr<int>)':

main.cpp:10:17: error: use of deleted function 
'std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) 
[with _Tp = int; _Dp = std::default_delete<int>]'

     using base::base;

                 ^~~~

In file included from /usr/local/include/c++/6.1.0/memory:81:0,

                 from main.cpp:1:

/usr/local/include/c++/6.1.0/bits/unique_ptr.h:356:7: note: declared here

       unique_ptr(const unique_ptr&) = delete;

       ^~~~~~~~~~

main.cpp: In function 'int main()':

main.cpp:14:39: note: synthesized method 'derived::derived(std::unique_ptr<int>)' 
first required here 

     derived df(std::make_unique<int>());

它似乎试图调用已删除的复制构造函数,但它运行得很好:

代码语言:javascript
运行
复制
void foo(std::unique_ptr<int>) {}

int main() {
    foo(std::make_unique<int>());
}

这个使用-fno-elide-constructors的示例打印出move called.

代码语言:javascript
运行
复制
struct move_only {
    move_only() { std::cout << "default called."; }
    move_only(move_only&&) { std::cout << "move called."; }
};

void foo(move_only) { }

int main() {
    foo(move_only{});
}

我意识到这两种情况并不相同,但似乎奇怪的是,需要&&来编译继承的构造函数示例,而不是后者。作为正常检查,显式执行move_only(const move_only&) = delete;并将签名更改为void foo(const move_only&) { }仍然会进行编译,除非这次甚至不调用move构造函数(可能是省略)。

最新标准草案的12.6.3说:

1当调用B类型的构造函数来初始化不同类型D的对象(即当构造函数被继承(namespace.udecl)时)时,初始化将继续进行,就好像使用默认的默认构造函数来初始化D对象和继承构造函数的每个基类子对象一样,但B子对象是通过调用继承的构造函数初始化的。完整的初始化被认为是一个函数调用;特别是,继承构造函数参数的初始化是在初始化D对象的任何部分之前进行的。[例子: 结构B1 { B1(int,.){ };// .struct D1 : B1 {使用B1::B1;//继承B1(int,.)int x;// . };void (){ D1 d(2,3,4);// OK: B1是通过调用B1(2,3,4)初始化的,// d.x是默认初始化(不执行初始化),// .} // .

所以它应该和foo(move_only)完全等价,对吧?

EN

回答 1

Stack Overflow用户

发布于 2016-05-06 06:17:39

这似乎是一个bug (报告为bug 70972)。N4140 N4140./8:

隐式定义的继承构造函数执行由用户为该类编写的内联构造函数所执行的类的初始化集合,该类的mem初始化器-列表中唯一的mem-初始化器-id,它将在使用声明的嵌套名称说明符和表达式列表中表示的基类命名为空(12.6.2)。如果用户编写的构造函数格式不正确,则程序的格式不正确。表达式列表中的每个表达式都是表单static_cast<T&&>(p),其中p是对应构造函数参数的名称,T是已声明的p类型。

换句话说,这里所讨论的继承构造函数应该是移动而不是复制它的参数。

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

https://stackoverflow.com/questions/37064993

复制
相关文章

相似问题

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