字符串成员的吸气剂让我很困惑。为什么返回一个
对对象(本例中为字符串)的引用(别名)?
const string& content() const {return *ptr;}
[return a reference] 有什么区别,
只是返回字符串?
string content() const { return *ptr;}
你可能会问这两者之间是否有区别
并且只返回指针
const string* content() const { return ptr;}
好吧,也许考虑一下字符串包含 2600 万个字符的场景,您可能希望避免复制它。
但如果只是为了评估您在这里学到的知识,您应该注意另一个问题(或者可能是 2 个)。
在 Lubuntu 18.04 上,使用 g++ (Ubuntu 7.3.0-27),字符串 s,没有数据,
std::string s;
cout << sizeof(s) << " " << s.size() << endl;
报告数字“32 0”。
std::string s ("01234567890123456789");
cout << sizeof(s) << " " << s.size() << endl;
报告值“32 20”
{
std::string s;
for (int i=0; i<1000000; i++)
{
for (char j='A'; j<='Z'; j++)
s.push_back(j);
}
cout << " " << sizeof(s) << " " << s.size() << endl;
}
这会报告值“32 26000000”
由此,您可以得出以下结论:a) 'string' 的实例与数据无关,占用 32 个字节。 b) 因为所有数据都驻留在其他地方 c) 所以 std::string 实例中的 32 个字节中的一些是指向动态内存中字符所在位置的指针。
嗯。
如果 obj 实例只有 32 个字节,那么你可能会问为什么 Example4 使用指针将这个 SMALL 对象(字符串实例)放入动态内存中……使用 8 个字节找到 32,然后需要一个第二个引用(字符串实例内部的某个指针)到达 Example4 字符串的字符。
同样,一个 std::vector 是 24 字节(不管有多少元素,也不管元素有多大)。 std::vector 负责内存管理,因此您不必这样做。
也许本课旨在帮助您发现和评估动态记忆中的内容以及自动记忆中的内容,以改进您的选择。
关键思想是 STL 库容器为您处理动态内存,从而大大简化您的工作。
或者,也许教授希望您更多地了解您正在使用的工具。在某些方面,标准容器将您与这些东西的工作方式隔离开来。也许这个任务是为了了解 std::string 的作用。
//这里是一些“g++ -std=c++17”代码,单步执行,说明了几个想法
#include <iostream>
using std::cout, std::endl;
#include <sstream>
using std::stringstream;
#include <iomanip>
using std::setfill, std::setw;
#include <string>
using std::string;
#include <cstring>
using std::strlen;
class Example4
{
string* ptr;
public:
Example4() : ptr(new string) {}
Example4 (const string& str) : ptr(new string(str)) {}
~Example4 () {delete ptr;}
// access content:
const string& content() const {return *ptr;}
const string* contentP() const {return ptr;}
string show(string lbl)
{
stringstream ss;
ss << "\n " << lbl
<< " . 5 4 3 2 1"
<< "\n . '09876543210987654321098765432109876543210987654321'"
<< "\n " << "*ptr : '" << *ptr << "'"
<< "\n " << "(*ptr).size() : " << (*ptr).size()
<< "\n " << " ptr->size() : " << ptr->size()
<< "\n " << "strlen((*ptr).c_str()) : " << strlen((*ptr).c_str())
<< "\n " << "strlen(ptr->c_str()) : " << strlen(ptr->c_str())
<< "\n\n " << "sizeof(*ptr) : " << sizeof(*ptr)
<< " @ 0x" << ptr << ',' // where ptr points to
<< "\n " << "sizeof (ptr) : " << sizeof(ptr)
<< "\n\n";
return ss.str();
}
};
class T996_t
{
public:
int operator()() { return exec(); }
private: // methods
int exec()
{
Example4 e4("Now is the time to answer all questions01234567890");
cout << "\n " << e4.show("Example4")
<< "\n '" << e4.content() << "'"
<< "\n '" << *e4.contentP() << "'\n\n"
<< endl;
{
std::string s;
cout << " " << sizeof(s) << " " << s.size() << endl;
}
{
std::string s("01234567890123456789");
cout << " " << sizeof(s) << " " << s.size() << endl;
}
{
std::string s;
for (int i=0; i<1000000; i++)
{
for (char j='A'; j<='Z'; j++)
s.push_back(j);
}
cout << " " << sizeof(s) << " " << s.size() << endl;
}
return 0;
}
}; // class T996_t
int main(int, char**) { return T996_t()(); }
这段代码在我的 Lubuntu 上编译和运行。我的make文件构建的编译命令以:
开头
g++ -std=c++17 -m64 -ggdb