我最初发布这个只是关于析构函数的问题,但现在我正在添加对默认构造函数的考虑.这是原始问题:
如果我想给我的类一个虚拟的析构函数,但是与编译器生成的析构函数相同,我可以使用
=default:Run Code Online (Sandbox Code Playgroud)class Widget { public: virtual ~Widget() = default; };但似乎我可以通过使用空定义减少输入来获得相同的效果:
Run Code Online (Sandbox Code Playgroud)class Widget { public: virtual ~Widget() {} };这两种定义的行为方式有何不同?
根据此问题的回复,默认构造函数的情况似乎相似.鉴于析构函数的" =default"和" {}"之间的含义几乎没有差异,默认构造函数的这些选项之间的含义几乎没有差别吗?也就是说,假设我想创建一个类型,其中该类型的对象将被创建和销毁,为什么我要说
Widget() = default;
Run Code Online (Sandbox Code Playgroud)
代替
Widget() {}
Run Code Online (Sandbox Code Playgroud)
?
如果在原始帖子违反某些SO规则后延长此问题,我深表歉意.为默认构造函数发布一个几乎完全相同的问题让我觉得不太理想.
c++ user-defined-functions default-constructor deleted-functions c++11
我一直在研究朋友编写的一些C++代码,并且我在使用gcc4.6编译时遇到了以前从未见过的错误:
error: use of deleted function
‘GameFSM_<std::array<C, 2ul> >::hdealt::hdealt()’ is implicitly deleted because the default definition would be ill-formed:
uninitialized non-static const member ‘const h_t FlopPokerGameFSM_<std::array<C, 2ul> >::hdealt::h’
Run Code Online (Sandbox Code Playgroud)
编辑:这来自使用boost MSM:Boost网页的部分代码
Edit2:= delete()源代码中没有任何地方使用过.
一般来说,这个错误意味着什么?发生此类错误时,我应该寻找什么?
在以下示例中,f()返回不完整类型的函数A被标记为已删除:
struct A;
A f() = delete;
Run Code Online (Sandbox Code Playgroud)
它被 GCC 接受,但不被 Clang 接受,Clang 抱怨道:
error: incomplete result type 'A' in function definition
Run Code Online (Sandbox Code Playgroud)
演示: https: //gcc.godbolt.org/z/937PEz1h3
根据标准,哪个编译器是正确的?
为了使对象不可复制,我们可以显式删除其复制构造函数和复制分配运算符。
我的问题是:什么是做正确的地方-在public,private或protected之类的部分?并且-这种选择有什么区别吗?
目前尚不清楚如果我在C++ 0x中删除虚拟方法会发生什么:
virtual int derive_func() = delete;
Run Code Online (Sandbox Code Playgroud)
这是否意味着这个类,从它继承的所有东西都无法定义/实现该derive_func()方法?或者这是非法/编译错误?
根据标准,
如果类X的定义没有显式地声明一个移动构造函数,那么当且仅当一个移动构造函数被隐式声明为默认值时
- X没有用户声明的复制构造函数,
- X没有用户声明的复制赋值运算符,
- X没有用户声明的移动赋值运算符,和
- X没有用户声明的析构函数.
现在以下无法编译
# include <utility>
class Foo
{
public:
Foo() = default;
Foo(Foo const &) = delete;
};
int main()
{
Foo f;
Foo g(std::move(f)); // compilation fails here
return 0;
}
Run Code Online (Sandbox Code Playgroud)
所以似乎删除的函数被认为是用户定义的,这是有道理的(它不是它的默认实现).但是,在那种特殊情况下,如何删除复制construtor/assignment mess默认移动构造函数/赋值?
我认为这个问题具有实际意义,因为手动生成和特别是 这种默认函数的维护是容易出错的,同时,诸如std::unique_ptr类成员之类的类的使用的(正当的)增加使得不可复制的类比以前更常见.
最近,我遇到了这个答案,它描述了如何初始化一个std::array非默认可构造元素.我并不感到惊讶,因为这个答案显然没有做任何默认构建.
相反,它std::array使用聚合初始化构建临时,然后移动(如果移动构造函数可用)或在函数返回时复制到命名变量.所以我们只需要移动构造函数或复制构造函数即可.
或者我认为......
然后是这段代码让我感到困惑:
struct foo {
int x;
foo(int x) : x(x) {}
foo() = delete;
foo(const foo&) = delete;
foo& operator=(const foo&) = delete;
foo(foo&&) = delete;
foo& operator=(foo&&) = delete;
};
foo make_foo(int x) {
return foo(x);
}
int main() {
foo f = make_foo(1);
foo g(make_foo(2));
}
Run Code Online (Sandbox Code Playgroud)
所有五个特殊成员构造函数/运算符都被显式删除,所以现在我不能从返回值构造我的对象,对吗?
错误.
令我惊讶的是,这在gcc中编译(使用C++ 17)!
为什么编译?显然foo要从函数返回一个make_foo(),我们必须构造一个foo.这意味着在main()我们foo从返回的函数中分配或构造一个函数foo.怎么可能?!
使用旧版本的g ++(4.8.0,MinGW)编译项目我发现此代码无法编译:
template<typename T>
void foo() = delete;
template<>
void foo<int>(){}
int main() {
foo<int>();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
似乎g ++甚至没有尝试寻找显式特化,如果它看到基本情况被删除.
mitalia@mitalia:~/scratch$ /opt/mingw32-dw2/bin/i686-w64-mingw32-g++ -std=c++11 buggy_deleted_template.cpp
buggy_deleted_template.cpp: In function 'int main()':
buggy_deleted_template.cpp:8:14: error: use of deleted function 'void foo() [with T = int]'
foo<int>();
^
buggy_deleted_template.cpp:5:6: error: declared here
void foo<int>(){}
^
mitalia@mitalia:~/scratch$ /opt/mingw32-dw2/bin/i686-w64-mingw32-g++ --version
i686-w64-mingw32-g++ (rubenvb-4.8.0) 4.8.0
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for …Run Code Online (Sandbox Code Playgroud) c++ templates template-specialization deleted-functions c++11
在阅读了@Mehrdad 最近的问题之后,哪些类应该是不可移动的,因此是不可复制的,我开始想知道是否存在可以复制但不能移动的类的用例.从技术上讲,这是可能的:
struct S
{
S() { }
S(S const& s) { }
S(S&&) = delete;
};
S foo()
{
S s1;
S s2(s1); // OK (copyable)
return s1; // ERROR! (non-movable)
}
Run Code Online (Sandbox Code Playgroud)
虽然S有一个复制构造函数,但它显然不会对CopyConstructible概念进行建模,因为这反过来又是MoveConstructible概念的改进,需要存在(未删除的)移动构造函数(参见§17.6.3.1/2,表21) .
是否有类似S上述类型的用例,可复制但不可 CopyConstructible 移动?如果没有,为什么不禁止在同一个类中声明复制构造函数和已删除的移动构造函数?
我有一个用例,我的对象不得以任何方式复制.我在下面写了一个夸张的复制构造函数和复制赋值运算符删除的完整列表.有这么多,我无法确定使用哪些,有时这让我变得偏执.我不必在我的代码中全部写出来,是吗?因此,为了防止任何类型的对象复制,我应该使用哪些对象?
MyClass ( MyClass &) = delete;
MyClass (const MyClass &) = delete;
MyClass ( MyClass &&) = delete;
MyClass (const MyClass &&) = delete;
MyClass operator=( MyClass &) = delete;
MyClass operator=(const MyClass &) = delete;
const MyClass operator=( MyClass &) = delete;
const MyClass operator=(const MyClass &) = delete;
MyClass & operator=( MyClass &) = delete;
MyClass & operator=(const MyClass &) = delete;
const MyClass & operator=( MyClass &) = delete;
const MyClass & operator=(const MyClass &) = …Run Code Online (Sandbox Code Playgroud) c++ copy-constructor copy-assignment deleted-functions implicit-methods