gpt4 book ai didi

通过引用存储的c++变体类成员

转载 作者:行者123 更新时间:2023-11-30 00:45:53 24 4
gpt4 key购买 nike

我正在尝试使用 std::variant 进行试验。我将 std::variant 存储为类的成员。在下面的代码中,如果变体按值存储,则一切正常,但如果变体按引用存储,则不起作用(对于 vector 情况,以及自定义对象)。这是为什么?

#include <variant>
#include <vector>
#include <iostream>


template<typename T>
using VectorOrSimple = std::variant<T, std::vector<T>>;


struct Print {
void operator()(int v) { std::cout << "type = int, value = " << v << "\n"; }
void operator()(std::vector<int> v) const { std::cout << "type = vector<int>, size = " << v.size() << "\n"; }
};


class A {
public:
explicit A(const VectorOrSimple<int>& arg) : member(arg) {
print();
}

inline void print() const {
visit(Print{}, member);
}

private:
const VectorOrSimple<int> member; // const VectorOrSimple<int>& member; => does not work
};


int main() {
int simple = 1;
A a1(simple);
a1.print();

std::vector<int> vector(3, 1);
A a2(vector);
a2.print();
}

参见 http://melpon.org/wandbox/permlink/vhnkAnZhqgoYxU1H对于工作版本,http://melpon.org/wandbox/permlink/T5RCx0ImTLi4gk5e对于有错误的崩溃版本:“在抛出 'std::bad_variant_access' 实例后调用终止 what(): 意外索引"

奇怪的是,当编写代码的 boost::variant 版本并将成员存储为引用时,它可以按预期工作(打印 vector size = 3 两次)与 gcc7.0(参见此处 http://melpon.org/wandbox/permlink/eW3Bs1InG383vp6M)并且不使用 clang 4.0 工作(在构造函数中打印 vector size = 3,然后在随后的 print() 调用中打印 vector size = 0,但没有崩溃)(参见此处 http://melpon.org/wandbox/permlink/2GRf2y8RproD7XDM)。

这很令人困惑。有人可以解释发生了什么吗?谢谢。

最佳答案

它不起作用,因为此语句 A a1(simple); 创建了一个临时变体对象!

然后您继续将所述临时绑定(bind)到您的 const 引用。但是在 a1 的构造结束后,临时变量立即超出范围,留下一个悬空引用。显然,创建拷贝是可行的,因为它始终涉及使用有效拷贝。

一个可能的解决方案(如果总是复制的性能让你担心)是按值接受一个变体对象,然后将它移动到你的本地拷贝中,就像这样:

explicit A(VectorOrSimple<int> arg) : member(std::move(arg)) {
print();
}

这将允许使用左值或右值调用构造函数。对于左值,您的成员 将通过移动源变体的拷贝来初始化,而对于rvalues,源的内容只会(最多)移动两次。

关于通过引用存储的c++变体类成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41139135/

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