繁体   English   中英

“= default”是否允许外线实现?

[英]Does “= default” allow out-of-line implementations?

通常我会看到标头中使用的= default语法。 我的理解是,这与在标头中明确实现函数的情况相同,请参阅下面的Foo

foo.h中

#pragma once

class Foo
{
public:
    Foo() = default;

    Foo(const Foo& other) = default;
};

纯粹出于好奇,可以在源文件中使用= default ,如下所示?

Bar.h

#pragma once

class Bar
{
public:
    Bar();

    Bar(const Bar& other);
};

Bar.cpp

#include "Bar.h"

Bar::Bar() = default;

Bar::Bar(const Bar&) = default;

据我所知,这相当于在cpp文件中显式实现这些功能。

上面的Bar示例使用gcc-5.1编译,但标准是否允许这种用法?

顺便说一句 ,在源文件中使用= default与标题有什么好处?

是的,这是合法的。 来自[dcl.fct.def.default]

显式默认函数和隐式声明函数统称为默认函数,实现应为它们提供隐式定义(12.1 12.4,12.8),这可能意味着将它们定义为已删除。 如果函数是用户声明的,并且在第一个声明中未明确默认或删除,则用户提供该函数。 用户提供的显式默认函数(即,在第一次声明后显式默认)是在明确默认的位置定义的; 如果将这样的函数隐式定义为已删除,则该程序格式错误。

强调我的

然后他们继续详细说明你的具体情况

 struct nontrivial1 { nontrivial1(); }; nontrivial1::nontrivial1() = default; // not first declaration 

因此,只要函数未被隐式标记为已删除,那么将定义函数,您可以在其中明确地将其默认。

顺便说一句,在源文件中使用= default与标题有什么好处?

唯一的“优势”我可以看到它允许现有的代码库更改其cpp文件以使用现代技术而无需更改头文件。 标准中甚至还有一个注释:

注意:在第一次声明后将函数声明为默认值可以提供高效的执行和简洁的定义,同时为不断发展的代码库提供稳定的二进制接口。

默认情况下,源文件而不是标头的一种潜在用法是使用带有unique_ptr的pimpl习惯用法。 它需要一个完整的构造和销毁类型,因此您无法在标题中定义这些特殊成员。 你必须这样做:

foo.h中

struct Foo { 
    struct Impl;
    unique_ptr<Impl> p;
    Foo();
    ~Foo();
};

Foo.cpp中

// Foo::Impl definition here

// now Impl isn't incomplete
Foo::Foo() = default;
Foo::~Foo() = default;

是的,特殊成员职能可能是“脱节”的; 编译器将生成正确的代码,它将按预期工作。

事实上,有一条规则涉及特殊成员在第一次申报时没有违约,然后他们被视为用户提供(因此非平凡)。

如果函数是用户声明的,并且在第一个声明中未明确默认或删除,则用户提供该函数。 用户提供的显式默认函数(即,在第一次声明后显式默认)是在明确默认的位置定义的; 如果将这样的函数隐式定义为已删除,则该程序格式错误。

链接到这里[dcl.fct.def.default] 通过以下示例详细说明您的情况;

 struct nontrivial1 { nontrivial1(); }; nontrivial1::nontrivial1() = default; // not first declaration 

它的用处在于它的作用,它提供了默认的实现,但不是在声明时,因此它是用户提供的 如上所述,这在处理尚未完成的类型时很有用,例如在使用pimpl习语时。 它也可以用于将您的类型标记为非平凡,因此禁止在需要简单类型的代码中使用它(例如std::is_trivial )。

行为发生了微小的变化。 其他TU而不是Bar.cpp看不到它们是默认的,因为它们只看到标题。 因此,将缺省值放在cpp中将使您的类不可轻易分配,而不是简单的可构造。

在某些情况下,您希望这样做:如果您的类将unique_ptr保存为不完整类型,那么在cpp中默认析构函数是一个好习惯,因为如果不这样做,那么使用您的类的类将被要求不完整类型的析构函数是可见的。

在源文件中实现时,方法不再是默认值,而是提供用户

暂无
暂无

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

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