【发布时间】:2020-12-29 09:59:25
【问题描述】:
我的上一个问题:
在下面的代码中,我需要变量auto ptr 到remain valid 和assertion 才能通过。
auto ptr = a.data();
看起来像这样:
+--------------+
| a.local_data | --\
+--------------+ \ +-------------+
>--> | "Some data" |
+-----+ / +-------------+
| ptr | -----------/
+-----+
#include <iostream>
#include <cassert>
using namespace std;
class Data
{
private:
char* local_data;
int _size = 0;
inline int length(const char* str)
{
int n = 0;
while(str[++n] != '\0');
return n;
}
public:
Data() {
local_data = new char[_size];
}
Data(const char* cdata) : _size { length(cdata) }{
local_data = new char[_size];
std::copy(cdata, cdata + _size, local_data);
}
int size() const { return _size; }
const char* data() const { return local_data; }
void swap(Data& rhs) noexcept
{
std::swap(_size, rhs._size);
std::swap(local_data, rhs.local_data);
}
Data& operator=(const Data& data)
{
Data tmp(data);
swap(tmp);
return *this;
}
};
int main()
{
Data a("Some data");
auto ptr = a.data(); // Obtains a pointer to the original location
a = Data("New data");
assert(ptr == a.data()); // Fails
return 0;
}
编辑:为了给出一些观点,以下内容在标准 C++ String 类中运行得非常好。
#include <iostream>
#include <string>
#include <cassert>
int main()
{
std::string str("Hello");
auto ptr = str.data();
str = std::string("Bye!");
assert(ptr == str.data());
std::cin.get();
return 0;
}
而且,我正在尝试实现相同的功能。
【问题讨论】:
-
指针仍然有效,因为你的类没有适当的析构函数并且
"Some data"永远不会被清理。您的示例在几个方面令人困惑。为什么operator=执行交换?此外,ptr只是a.local_data的副本。改变一个对另一个没有任何影响。它们是指向相同数据的独立指针。 -
但是,在这种情况下它确实发生了变化。我一步一步地检查了 Visual Studio IDE,观察了内容及其内存地址。在此处查看运行示例:onlinegdb.com/HybpyOO6P
-
ptr仍然有效。a.local_data更改。它们不再指向相同的数据。由于您正在使用临时对象执行交换,因此您的示例也会崩溃,因此a不再有效。 -
@AlbinM 此外,不能保证断言不会在标准字符串类中失败。如果新文本很长(比如 100 个字符),它很可能会失败。这是一种实现定义的行为,在这种情况下断言会通过或失败。
-
顺便说一句,您的
length函数将失败并返回一个空字符串。