- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我是 C++ 的新手,也是使用 RAII 删除分配的内存的新手。我编写这段代码作为自动分配和稍后删除字符数组所需的示例。我知道那里有一个字符串类,但我想我会先从旧的东西开始。这个样本看起来正确吗?这是其他人创建字符串并自动删除它的方式吗?
#include <iostream>
using namespace std;
class StringGetter
{
private:
char* theString;
public:
StringGetter(char* name)
{
this->theString = new char[1024];
strcpy_s(this->theString, strlen(name) + 1, name);
}
char* GetString()
{
return this->theString;
}
~StringGetter()
{
delete[] this->theString;
}
};
int main()
{
char* response;
{
StringGetter getter("testing");
response = getter.GetString();
}
cin.get(); // pauses the console window
}
最佳答案
看起来您已经掌握了主要思想,但还有几件事值得一提。
1) 正如@chris 提到的,您忘记了复制构造函数、复制赋值运算符、移动构造函数和移动赋值运算符。复制应该是手动写入或禁用,移动可以默认。 (又名你没有遵守 5 的规则)
2) 更喜欢使用std::unique_ptr
来表示所有权。它已经为您完成了所有艰苦的工作。通过将包装的字符串保存在 std::unique_ptr
中,复制/移动特殊函数的默认版本将保持正确性(尽管如果您希望启用复制操作,您仍然需要实现它们).
这可能是这样的:
class StringGetter {
public:
explicit StringGetter(char* name) {
strSize = strlen(name);
str = std::unique_ptr<char[]>(new char(strSize+1));
std::copy_n(name, strSize + 1, str.get());
}
StringGetter(const StringGetter& other) {
strSize = other.strSize;
str = std::unique_ptr<char[]>(new char(strSize+1));
std::copy_n(other.str.get(), strSize + 1, str.get());
}
StringGetter(StringGetter&& other) = default;
StringGetter& operator=(const StringGetter& rhs) {
auto temp = rhs;
swap(temp);
return *this;
}
StringGetter& operator=(StringGetter&& rhs) = default;
const char* getString() const noexcept {
return str.get();
}
void swap(StringGetter& other) {
std::swap(str, other.str);
std::swap(strSize, other.strSize);
}
private:
std::unique_ptr<char[]> str;
int strSize;
};
杂项:
1) 注意 std::unique_ptr
处理 RAII。当我在复制构造函数中替换“str”时,它会自动删除旧字符串。
2) 我调整动态分配内存的大小以匹配输入字符串。这可以防止溢出/浪费内存。
3) 构造函数是明确的
。这可以防止不需要的转换。经验法则是对所有单参数构造函数使用 explicit
关键字。
4) 我将 getString
设为常量,这样您仍然可以在类的 const
实例上调用它。
5) 我用 std::copy_n
替换了 str-family 复制函数。它更通用,可以避免在晦涩的情况下出现某些陷阱。
6) 我在复制赋值运算符中使用了复制交换惯用语。这促进了代码重用/避免重复。
7) 当 C++14 发布时,将 std::unique_ptr
构造函数调用替换为 std::make_unique
以增加异常安全性并消除冗余。
关于C++ RAII - 我有这个权利吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20862985/
Wikipedia (和其他一些来源)指出: In RAII, holding a resource is tied to object lifetime: resource allocation (
关闭。这个问题是off-topic .它目前不接受答案。 想改进这个问题? Update the question所以它是on-topic对于堆栈溢出。 9年前关闭。 Improve this que
我过去主要认为 RAII 是关于使用对象生命周期来避免资源泄漏,这在实践中对我很有用。但是我最近讨论了什么是 RAII 模式,什么不是,这让我在网上搜索了更多的定义和评论,结果增加了更多的困惑而不是清
我编写此代码是为了递归遍历文件夹树并列出文件大小(以字节为单位)。 由于我使用的是 winapi 并且有一个 Handle应该打开和关闭,我应该在这段代码上实现 RAII,问题是在线论坛上给出的例子(
我有一个 foo 类。对 foo 的操作需要调用 foo::open()、一些 foo::write(),并且必须以 foo::close() 调用结束: #include class foo {
问题 如何在 RAII 作用域内初始化一个对象,并在该作用域外使用它? 背景 我有一个全局锁,可以用 lock() 和 unlock() 调用。 我有一个类型,LockedObject,只有在全局锁锁
在性能方面,是否有更好的方法来做到这一点? 例如,创建一个名为 arraydata 的类/结构,它分配一些对齐的内存供使用(通过 .dataPtr 提供的指针): class arraydata//t
我是 C++ 的新手,也是使用 RAII 删除分配的内存的新手。我编写这段代码作为自动分配和稍后删除字符数组所需的示例。我知道那里有一个字符串类,但我想我会先从旧的东西开始。这个样本看起来正确吗?这是
(我修改了原来的问题更有意义) 关于 return 语句,Raii 对象是否在 return 语句之前/之后/之间销毁? 例如 size_t advance() { boost::lock_g
我刚刚了解了 RAII。据我了解,RAII 的定义就是它的名称本身。例如,(假设 A 是一个类),考虑下面的函数: void foo(){ A a; a.init(); // Do
由于 RAII,C++ 中没有 finally block 。现在,如果我有一个指针对象,并且其中一个方法发生异常,将如何删除该对象?。这是我编写的示例代码。 class A { public:
如果有一个类: class classA { public: int z = 5; }; 我在编写 classA Aobject 时理解 RAII,但是如果我想声明一个全局指针,我该怎么办?
我想围绕使用 malloc/free 的 C 库编写一个库包装类 (LibWrap)。为此,我想使用 C++ 的 RAII 来分配和释放内存。我使用 lib_address 作为我将从图书馆收到的随机
直到我关于 RAII 和堆栈展开的“相互缠绕”(因为缺少更好的词)的概念是/是相当(如果不是完全)错误的。我的理解是,使用 RAII 可以防止任何/所有资源泄漏——甚至可能由未处理的异常引起的泄漏。
我创建了一个抽象类,然后创建了继承这个抽象类的子类。 class A{ public: virtual A* clone() const = 0; virtual A* creat
#define _CRTDBG_MAP_ALLOC #include #include struct A { A(char* p) : p(p) {} ~A
Scheme 中是否有实现资源获取即初始化的方案? 我知道 RAII 在 GC-ed 语言中效果不佳(因为我们不知道对象何时被销毁)。然而,Scheme 有一些不错的东西,比如延续、动态风和闭包——有
为了安全地使用 C++,我想封装几个 C 函数。有一个 C 函数,它接受指向数组的原始指针及其大小,比如 - void function(char* bufferToFill, size_t bufs
上次我看到一些视频,其中 Stroustrup 先生谈论 C++ 中的 RAII。我想了解更多并找到此页面: https://www.securecoding.cert.org/confluence/
在我的代码中我使用 HANDLE来自 windows.h .它们的用法如下 HANDLE h; if (!openHandleToSomething(arg1, arg2, &h)) { th
我是一名优秀的程序员,十分优秀!