不能将数组运算符用于基于数组的指针(读取访问冲突)
Posted
技术标签:
【中文标题】不能将数组运算符用于基于数组的指针(读取访问冲突)【英文标题】:can't use array operator to array-based pointers (read access violation) 【发布时间】:2019-07-18 16:05:44 【问题描述】:基本上我想要实现的是使用指针,避免使用new
关键字来获得与其他一些语言相同的复制行为(如果我们交谈,运算符=
将右操作数的引用分配给左操作数关于对象,类似于 shared_ptr
应该提供的)。如果我不使用数组运算符[]
,我将展示的内容似乎有效。为什么会发生这种情况,我该如何解决?
// Declaration way before
std::vector<int>* test;
test = &std::vector<int>();
(*test)[1] = 0;
// Declaration way before
std::map<std::string, int>* test;
test = &std::map<std::string, int>();
(*test)["a"] = 0;
错误发生在两者的最后一行。
【问题讨论】:
test = &std::vector<int>();
创建一个向量,获取它的地址,然后向量立即停止存在。
不要试图让 C++ 表现得像其他语言一样。往往效果不佳。如果你想要一个引用,只需声明一个引用。
即使*test
指向一个实际的空向量,(*test)[1]
也会尝试访问一个不存在的元素。
相信我们,它确实不再存在。您正在做的事情称为未定义行为,一种可能的结果是它“有效”。
@uIM7AI9S 您的错误会导致未定义的行为。这意味着任何事情都可能发生。 C++ 中的许多(大多数?)错误不需要崩溃或诊断,这样的代码似乎可以工作一段时间。但事实是您的向量不存在,push_back
似乎只能工作。如果你依赖它,你最终将不可避免地开始在此处或代码的其他(看似无关的)部分中看到奇怪的崩溃和错误。不可能通过反复试验来学习 C++,没有明显的错误迹象并不能证明正确性。
【参考方案1】:
test = &std::vector<int>();
这不是有效的 C++。不能取临时地址。
不幸的是,作为扩展,Visual Studio 确实允许您这样做;你得到的指针是立即悬空(因为临时死在行尾)。然后,您尝试对向量(不存在)执行的所有操作都有未定义的行为。
(即使它是一个有效的指针,你也在尝试索引不存在的元素。)
只要您在范围内的某个位置保留一个适当的命名对象,您就可以做您想做的事。您可以获得指向该对象的指针并在所有地方获取您的引用语义。但是,这是危险的,因为很难确保指向的对象在需要时仍然存在。这就是存在智能指针的原因。
在 C++ 中,你最好坚持价值语义。最好按设计使用该语言。
【讨论】:
【参考方案2】:您正在为指针分配对临时向量的引用。临时对象立即消失,您的指针悬空。
您还尝试访问具有0
大小的向量的第二个元素。
你可以试试这个,但我们已经不在 new
delete
时代了。
std::vector<int>* test;
test = new std::vector<int>(2);
(*test)[1] = 0;
// done with test
delete test;
【讨论】:
【参考方案3】:不能对基于数组的指针使用数组运算符
你可以,如果你的指针指向一个对象。你的没有。
使用指针,避免使用 new 关键字来获得与其他语言相同的复制行为
您还没有真正表现出您想要什么行为,或者说您要模仿哪种语言,但总的来说:用语言 B 编写语言 A 代码是一个坏主意。两者将有不同的约定、习语和微妙之处。
如果您确实坚持要编写看起来像另一种语言的 C++,您需要弄清楚您需要什么特定行为,以及如何在 C++ 中实现它以使其看起来相似。这通常需要大量工作,而编写看起来符合您想要的方式并且恰好可以编译的 C++ 代码并不是一个足够的解决方案。
正如 Lightness 指出了你的近似错误,我只想提一下,通过编写一个金丝雀类型来检查你对这些事情的理解是微不足道的,比如
struct Canary
~Canary() cout << "Canary dtor\n";
Canary() cout << "Canary default ctor\n";
Canary(Canary &&) cout << "Canary move ctor\n";
Canary(const Canary &) cout << "Canary copy ctor\n";
Canary& operator=(Canary &&) cout << "Canary move assignment\n"; return *this;
Canary& operator=(const Canary &) cout << "Canary copy assignment\n"; return *this;
;
Canary *c = &Canary();
现在您可以轻松地在调试器中单步调试您的代码,或者只是运行它并观察输出...
【讨论】:
以上是关于不能将数组运算符用于基于数组的指针(读取访问冲突)的主要内容,如果未能解决你的问题,请参考以下文章