【发布时间】:2019-09-09 08:20:03
【问题描述】:
我正在尝试创建一个通用类,它可以以最基本的形式表示任何对象,位。为此,我创建了一个由字符数组(本质上是字节)和字符组成的对象组成的 Union。不幸的是,在构建时,我的工会收到了一个奇怪的警告和错误。
警告:“析构函数被隐式定义为已删除。”
错误:“正在尝试引用已删除的函数。”
(都出现在我的联合定义之后的行)
我知道您可以为结构、类和联合创建自定义析构函数,但如果您不释放动态内存,则不需要,对吗?然而不知何故,我从未定义过的析构函数被自动调用,编译器隐式删除了它。因此出现错误。
接下来我尝试在联合中定义析构函数;它什么也没做,因为我从来没有向操作系统索要额外的内存。它再次被删除。我需要弄清楚为什么编译器会删除我的函数,然后在删除它后尝试调用它时导致错误。
我尝试在 Microsoft Visual Studio 列表中查找此错误,结果发现不公开构造函数会导致此错误。此外,在这里在线查看时,我发现复制构造函数通常会导致错误,因为它从未定义过。所以我通过创建自己的类并使用复制构造函数 = 对其进行了测试。它工作得很好,但是在尝试将它与我的 typeAsChar 类一起使用时给了我同样的错误。有趣的是,当我将我的类与 C 默认结构、int、double 等一起使用时,不会调用此错误。
这是导致问题的代码。
template <class type>
union typeAsChar
{
type obj;
char arr[sizeof(type)];
};
template <class type>
class wontWork
{
public:
wontWork() {/* Do nothing, no data entered */}
wontWork(const type& obj) { foo.obj = obj; }
~wontWork() {/* When this goes out of scope, the default
destructor of the member 'type' should be called */}
typeAsChar<type> foo;
};
int main()
{
double testNum = 12345;
std::string testStr = "Hello World\n";
wontWork<std::string> test1(testStr); // has error
std::cout << test1.foo.obj;
wontWork<double> test2(testNum); // No error
std::cout << test2.foo.obj;
return 0;
}
奇怪的是,在 wontWork<std::string> 被注释掉的情况下,它可以完美地编译和运行,但是当我的类是使用标准 c 结构(int、double 等)以外的任何对象创建时会失败。任何关于此事的澄清将不胜感激。
【问题讨论】:
-
unions 并不是真正的 C++ 兼容。它们实际上是 C 的保留。在 C++ 中,您应该使用std::variant而不是联合,以避免这个问题。 -
我会试试的
-
感谢您的建议,但变体对我不起作用,因为我需要将一个特定类型的对象传递给它,然后是一个字符数组(理想情况下与传入的第一种类型)。我可以传入数组的唯一方法是通过指向 char 的指针,但我不想传入并修改指针。相反,我希望修改它指向的字符数组。
-
好吧,对于初学者来说,无论是通过联合还是变体,您实际上都无法将“字符数组”转换为 C++
std::string。 C++ 不能以这种方式工作。您会惊讶地发现sizeof(std::string)是一个非常小的值,并且无论字符串为空还是包含“战争与和平”的整个文本,它的大小始终相同。那么,鉴于此,您希望如何实现您的目标?抱歉,但 C++ 根本无法以这种方式工作。 -
通过字符数组。字面上地。 char arr[50 /*在这里选择一个随机数 */].本质上是一个 c 字符串,而不是 std::string
标签: c++ templates destructor implicit