gpt4 book ai didi

c++ - QVector 要求默认构造函数的原因是什么?

转载 作者:可可西里 更新时间:2023-11-01 18:39:57 28 4
gpt4 key购买 nike

我可以看到类被视为调用默认构造函数所需的复杂对象:

void QVector<T>::defaultConstruct(T *from, T *to)
{
if (QTypeInfo<T>::isComplex) {
while (from != to) {
new (from++) T();
}
...
}

但不清楚为什么需要在 QVector 的“隐藏”区域构造对象。我的意思是这些对象根本无法访问,那么为什么不只保留内存而不是创建真正的对象呢?

作为一个额外的问题,我想问一下,如果我想要一个非默认可构造对象的数组,我可以安全地替换 QVector<T> 吗?与 QVector<Wrapper<T> ?其中 Wrapper是这样的:

class Wrapper {
public:
union {
T object;
bool hack;
};
Wrapper() {}
Wrapper(const T &t) : object { t } {}
Wrapper(const Wrapper &t) : object { t.object } {}

Wrapper &operator=(const Wrapper &value) {
object = value.object;
return *this;
}

~Wrapper() {}
};

最佳答案

QVector 为非默认构造类型 T 工作很容易:

#define QVECTOR_NON_DEFAULT_CONSTRUCTIBLE(Type) \
template <> QVector<Type>::QVector(int) = delete; \
template <> void QVector<Type>::resize(int newSize) { \
Q_ASSERT(newSize <= size()); \
detach(); \
} \
template <> void QVector<Type>::defaultConstruct(Type*, Type*) { Q_ASSERT(false); }

宏需要出现在 MyType 声明之后 - 在头文件中(如果有的话),并且它必须在命名空间或全局范围内:

struct MyType { ... };
QVECTOR_NON_DEFAULT_CONSTRUCTIBLE(MyType)

struct A {
struct MyType2 { ... };
};
QVECTOR_NON_DEFAULT_CONSTRUCTIBLE(A::MyType2);

不,包装器不正确。它不会破坏 object 成员。它还不提供移动语义,不防止被默认构造等。hack union 成员不是必需的。 union 中的任何内容都不会为您默认构建。

这是一个更正确的包装器 - 它非常类似于 std::optional。参见 here查看 optional 需要多少细微差别:)

// https://github.com/KubaO/stackoverflown/tree/master/questions/vector-nodefault-33380402

template <typename T> class Wrapper final {
union {
T object;
};
bool no_object = false;
void cond_destruct() {
if (!no_object)
object.~T();
no_object = true;
}
public:
Wrapper() : no_object(true) {}
Wrapper(const Wrapper &o) : no_object(o.no_object) {
if (!no_object)
new (&object) T(o.object);
}
Wrapper(Wrapper &&o) : no_object(o.no_object) {
if (!no_object)
new (&object) T(std::move(o.object));
}
Wrapper(const T &o) : object(o) {}
Wrapper(T &&o) : object(std::move(o)) {}
template <class...Args> Wrapper(Args...args) : object(std::forward<Args>(args)...) {}
template <class U, class...Args> Wrapper(std::initializer_list<U> init, Args...args) :
object(init, std::forward<Args>(args)...) {}
operator T& () & { assert(!no_object); return object; }
operator T&& () && { assert(!no_object); return std::move(object); }
operator T const&() const& { assert(!no_object); return object; }
Wrapper &operator=(const Wrapper &o) & {
if (no_object)
::new (&object) T(o);
else
object = o.object;
no_object = false;
return *this;
}
Wrapper &operator=(Wrapper &&o) & {
if (no_object)
::new (&object) T(std::move(o.object));
else
object = std::move(o.object);
no_object = false;
return *this;
}
template<class... Args> T &emplace(Args&&... args) {
cond_destruct();
::new (&object) T(std::forward<Args>(args)...);
no_object = false;
return object;
}
~Wrapper() {
cond_destruct();
}
};

由于赋值运算符是引用限定的,它不允许分配给右值,所以它具有恕我直言的积极属性,以下不会编译:

Wrapper<int>() = 1   // likely Wrapper<int>() == 1 was intended

关于c++ - QVector 要求默认构造函数的原因是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33380402/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com