【问题标题】:Deprecated implicitely-declared copy constructor已弃用的隐式声明的复制构造函数
【发布时间】:2018-09-27 19:25:39
【问题描述】:

我正试图围绕隐式声明的复制构造函数的一个奇怪特征。举个例子。一旦用户实现了自定义析构函数,复制构造函数就不再是微不足道的了,但仍然会生成。

#include <type_traits>
#include <cstdio>

struct test {
    test() = default;
    ~test() {
    }
    test(const test&) = default;
    int i{42};
};
static_assert(std::is_copy_constructible_v<test>, "werks"); // OK
static_assert(std::is_trivially_copy_constructible_v<test>, "sad"); // FAILS

int main() {
    test t;
    test t2(t);
    printf("%d\n", t2.i);
    return 0;
}

在线版:https://godbolt.org/z/t-8_W3

我对普通构造函数的理解是它们是由编译器生成的。但是,cppreference 声明:

隐式定义的复制构造函数的生成是 如果 T 具有用户定义的析构函数或用户定义的副本,则不推荐使用 赋值运算符。

因此,隐式声明的构造函数似乎还有另一种状态,即“已弃用”。它不是“微不足道的”,也不是用户实现的,但仍然由您的编译器生成……对吗?有人知道用于验证构造函数是否“已弃用”的类型特征或解决方法吗?

【问题讨论】:

  • "deprecated" 表示它仍然会发生,但不鼓励您的程序依赖它,并且可能会在未来的标准中删除

标签: c++ c++11 c++17 typetraits static-assert


【解决方案1】:

is_trivially_copy_constructible&lt;T&gt; 还要求 T 可以简单地破坏。这个特征检查的是假设变量定义是否:

T t(declval<T const&>());

不会调用任何重要的操作。但是test 并不是可以轻易破坏的,而且这种破坏是隐含在该构造中的。

如果将~test() { } 更改为~test() = default,断言将不再触发。


关于弃用隐式定义的构造函数的注释无关紧要,因为您有一个显式默认的复制构造函数。

【讨论】:

  • 这是你指的段落? “在许多实现中,is_nothrow_copy_constructible 还检查析构函数是否抛出,因为它实际上是 noexcept(T(arg))。同样适用于 is_trivially_copy_constructible,在这些实现中,它还要求析构函数是微不足道的:GCC 错误 51452 LWG 问题 2116。 "所以这是一个错误?
  • 因为我认为“琐碎”意味着由编译器生成。在示例中,它是由您的编译器生成的。所以应该是微不足道的。
  • @scx “琐碎”和“由编译器生成”根本不是同一件事。 “琐碎”在 C++ 中具有非常特殊的含义。考虑struct S { std::string m; };这个类有编译器生成的拷贝构造函数和析构函数,两者都不是微不足道的。
  • 这是经理所说的“它是一个错误”:D 无论如何,感谢您的帮助!
猜你喜欢
  • 2012-07-19
  • 1970-01-01
  • 2014-11-26
  • 2016-12-28
  • 1970-01-01
  • 2018-06-11
  • 2021-05-12
  • 1970-01-01
  • 2017-05-02
相关资源
最近更新 更多