- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
class Word
{
private:
std::string w;
public:
Word(std::string w) : w(w) {}
};
class Sentence
{
private:
std::list<Word *> words;
public:
Sentence(std::list<Word *> words) : words(words) {}
~Sentence() {
for (auto word : words)
delete word;
words.clear();
}
};
int main() {
Word *word1 = new Word("abc");
Word *word2 = new Word("def");
Sentence sentence1( std::list<Word *>({word1, word2}) );
Sentence sentence2 = sentence1;
return 0;
}
(实际类更大;我确实需要使用指向 Word
的指针,在其他函数中分配)对象 word1
和 word2
将被删除两次。我有这些解决问题的选择:
Word * Word::clone(const Word *word)
和 Sentence * Sentence::clone(const Sentence *s)
并在 中调用它们>Sence::operator=
。但是在这种情况下,我的程序使用了过多的内存(句子中的单词是相同的,但在内存中分配了两次)。bool isCopy
添加到Sentence
并仅在isCopy == false
时删除单词。我认为这看起来很愚蠢。那么我应该怎么做更好呢?
最佳答案
永远不要使用指向任何东西的指针集合。如果您必须有 word 的堆分配实现,请将其包装在具有类似值行为的句柄类中。
然后存入list(或vector等)
例如:
struct word_impl {}; // big thing
auto clone(const word_impl& impl) -> std::unique_ptr<word_impl> {
// clone could if you wished, defer to a virtual clone method
// on word_impl
return std::make_unique<word_impl>(impl);
}
struct word
{
// construct from letters
word(const char* letters) : impl_ { std::make_unique<word_impl>(letters) } { }
// let's make it copyable
word(const word& r) : impl_ { clone(r.impl_) } {}
word& operator=(const word& r) {
if (this != std::addressof(r)) {
impl_ = clone(r.impl_);
}
return *this;
}
// and moveable
word(word&& r) = default;
word& operator=(word&& r) = default;
private:
std::unique_ptr<word_impl> impl_;
}
这是一个完整的、可编译的示例,它根据共享词和可克隆词来表达词对象。
我在这里尝试做的是将“共享”的关注点与对单词的实际操作分开。
这使您可以在客户端使用相同的代码来创建一个由独特词或共享词组成的句子。用户不需要了解单词的内部运作方式,甚至不需要了解其内存是如何管理的。他只需要知道它可以被复制、打印和比较(在这种情况下)。
还有一个进一步的操作,将unique_word转换为shared_word。
#include <memory>
#include <iostream>
#include <vector>
#include <iomanip>
#include <boost/operators.hpp>
//
// define some protocols that a handle class can inherit from. These
// translate methods on the handle onto methods on the implementation
//
template<class Handle>
struct implement_ostream_protocol {
friend std::ostream &operator<<(std::ostream &os, const implement_ostream_protocol &proto) {
auto &ref = static_cast<const Handle &>(proto).get_reference();
return os << ref;
}
};
template<class Handle, class Comp = std::less<>>
struct implement_less_than_protocol {
friend bool operator<(const implement_less_than_protocol &l, const implement_less_than_protocol &r) {
auto &lr = static_cast<const Handle &>(l).get_reference();
auto &rr = static_cast<const Handle &>(r).get_reference();
auto comp = Comp();
return comp(lr, rr);
}
};
template<class Handle>
struct implement_setValue_protocol {
template<class T>
decltype(auto) setValue(T&& value)
{
auto &lr = static_cast<Handle &>(*this).get_reference();
return lr.setValue(std::forward<T>(value));
}
};
//
// this is the implementation of a word
//
struct word_impl {
word_impl(const char *letters) : word_(letters) {
std::cout << "constructed word: " << word_ << std::endl;
}
word_impl(const word_impl &r) : word_(r.word_) {
std::cout << "copied word: " << word_ << std::endl;
}
word_impl(word_impl &&r) noexcept : word_(std::move(r.word_)) {
std::cout << "moved word: " << word_ << std::endl;
}
word_impl &operator=(const word_impl &r) {
if (this != std::addressof(r)) {
word_ = r.word_;
std::cout << "assigned word: " << word_ << std::endl;
}
return *this;
}
word_impl &operator=(word_impl &&r) noexcept {
if (this != std::addressof(r)) {
word_ = std::move(r.word_);
std::cout << "move-assigned word: " << word_ << std::endl;
}
return *this;
}
// some wordy operations
bool comes_before(const word_impl &r) const {
return word_ < r.word_;
}
void setValue(const char* p)
{
std::cout << "value changed from " << word_ << " to " << p << "\n";
word_ = p;
}
// write myself
friend std::ostream &operator<<(std::ostream &os, const word_impl &r) {
return os << std::quoted(r.word_);
}
struct comes_before_op {
bool operator()(const word_impl &l, const word_impl &r) const {
return l.word_ < r.word_;
}
};
std::string word_;
}; // big thing
//
// these are the protocols I want all types of word handles to support
//
template<class Handle>
struct word_impl_protocols
: implement_ostream_protocol<Handle>,
implement_less_than_protocol<Handle, word_impl::comes_before_op> ,
implement_setValue_protocol<Handle>,
boost::less_than_comparable<word_impl_protocols<Handle>>
{
};
auto clone(const word_impl &impl) -> std::unique_ptr<word_impl> {
// clone could if you wished, defer to a virtual clone method
// on word_impl
return std::make_unique<word_impl>(impl);
}
//
// lets make a copyable word that clones its implementation
//
struct unique_word
: word_impl_protocols<unique_word> {
// construct from letters
unique_word(const char *letters) : impl_{std::make_unique<word_impl>(letters)} {}
// let's make it copyable
unique_word(const unique_word &r) : impl_{clone(*r.impl_)} {}
unique_word &operator=(const unique_word &r) {
if (this != std::addressof(r)) {
impl_ = clone(*r.impl_);
}
return *this;
}
// and moveable
unique_word(unique_word &&r) noexcept = default;
unique_word &operator=(unique_word &&r) noexcept = default;
word_impl const &get_reference() const {
return *impl_;
}
word_impl &get_reference() {
return *impl_;
}
// warning - destructive - provides a means to create a
// shared word from a unique_word
auto share() {
return std::shared_ptr<word_impl> {std::move(impl_)};
}
private:
std::unique_ptr<word_impl> impl_;
};
//
// and a word type that shares its implementation
//
struct shared_word
: word_impl_protocols<shared_word> {
shared_word(const char *letters) : impl_{std::make_shared<word_impl>(letters)} {}
shared_word(unique_word &&source) : impl_{source.share()} {}
const word_impl &get_reference() const { return *impl_; }
word_impl &get_reference() { return *impl_; }
std::shared_ptr<word_impl> impl_;
};
int main() {
std::cout << "creating first sentence:\n";
std::vector<unique_word> sentence1 = [] {
std::vector<unique_word> result;
result.emplace_back("abc");
result.emplace_back("def");
result.emplace_back("ghi");
return result;
}();
std::cout << "copying first sentence:\n";
std::vector<unique_word> sentence2 = sentence1;
std::sort(sentence2.begin(), sentence2.end(), std::greater<>());
std::copy(sentence1.begin(), sentence1.end(), std::ostream_iterator<unique_word>(std::cout, ", "));
std::cout << std::endl;
std::copy(sentence2.begin(), sentence2.end(), std::ostream_iterator<unique_word>(std::cout, ", "));
std::cout << std::endl;
std::cout << "converting first sentence to shared words:\n";
std::vector<shared_word> sentence3;
for (auto& unique : sentence1)
{
sentence3.emplace_back(std::move(unique));
}
std::copy(sentence3.begin(), sentence3.end(), std::ostream_iterator<shared_word>(std::cout, ", "));
std::cout << std::endl;
std::cout << "copying sentence of shared words:\n";
auto sentence4 = sentence3;
std::cout << "changing the first word of a shared word sentence:\n";
sentence3.at(0).setValue("xyz");
std::copy(sentence3.begin(), sentence3.end(), std::ostream_iterator<shared_word>(std::cout, ", "));
std::cout << std::endl;
std::copy(sentence4.begin(), sentence4.end(), std::ostream_iterator<shared_word>(std::cout, ", "));
std::cout << std::endl;
}
预期输出:
creating first sentence:
constructed word: abc
constructed word: def
constructed word: ghi
copying first sentence:
copied word: abc
copied word: def
copied word: ghi
"abc", "def", "ghi",
"ghi", "def", "abc",
converting first sentence to shared words:
"abc", "def", "ghi",
copying sentence of shared words:
changing the first word of a shared word sentence:
value changed from abc to xyz
"xyz", "def", "ghi",
"xyz", "def", "ghi",
关于c++ - 内存管理的正确方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41306594/
我一直在阅读有关汇编函数的内容,但对于是使用进入和退出还是仅使用调用/返回指令来快速执行,我感到很困惑。一种方式快而另一种方式更小吗?例如,在不内联函数的情况下,在汇编中执行此操作的最快(stdcal
我正在处理一个元组列表,如下所示: res = [('stori', 'JJ'), ('man', 'NN'), ('unnatur', 'JJ'), ('feel', 'NN'), ('pig',
最近我一直在做很多网络或 IO 绑定(bind)操作,使用线程有助于加快代码速度。我注意到我一直在一遍又一遍地编写这样的代码: threads = [] for machine, user, data
假设我有一个名为 user_stats 的资源,其中包含用户拥有的帖子、评论、喜欢和关注者的数量。是否有一种 RESTful 方式只询问该统计数据的一部分(即,对于 user_stats/3,请告诉我
我有一个简单的 api,它的工作原理是这样的: 用户创建一个请求 ( POST /requests ) 另一个用户检索所有请求 ( GET /requests ) 然后向请求添加报价 ( POST /
考虑以下 CDK Python 中的示例(对于这个问题,不需要 AWS 知识,这应该对基本上任何构建器模式都有效,我只是在这个示例中使用 CDK,因为我使用这个库遇到了这个问题。): from aws
Scala 中管理对象池的首选方法是什么? 我需要单线程创建和删除大规模对象(不需要同步)。在 C++ 中,我使用了静态对象数组。 在 Scala 中处理它的惯用和有效方法是什么? 最佳答案 我会把它
我有一个带有一些内置方法的类。这是该类的抽象示例: class Foo: def __init__(self): self.a = 0 self.b = 0
返回和检查方法执行的 Pythonic 方式 我目前在 python 代码中使用 golang 编码风格,决定移动 pythonic 方式 例子: import sys from typing imp
我正在开发一个 RESTful API。其中一个 URL 允许调用者通过 id 请求特定人员的记录。 返回该 id 不存在的记录的常规值是什么?服务器是否应该发回一个空对象或者一个 404,或者其他什
我正在使用 pathlib.Path() 检查文件是否存在,并使用 rasterio 将其作为图像打开. filename = pathlib.Path("./my_file-name.tif") 但
我正在寻找一种 Pythonic 方式来从列表和字典创建嵌套字典。以下两个语句产生相同的结果: a = [3, 4] b = {'a': 1, 'b': 2} c = dict(zip(b, a))
我有一个正在操裁剪理设备的脚本。设备有时会发生物理故障,当它发生时,我想重置设备并继续执行脚本。我有这个: while True: do_device_control() device
做组合别名的最pythonic和正确的方法是什么? 这是一个假设的场景: class House: def cleanup(self, arg1, arg2, kwarg1=False):
我正在开发一个小型客户端服务器程序来收集订单。我想以“REST(ful)方式”来做到这一点。 我想做的是: 收集所有订单行(产品和数量)并将完整订单发送到服务器 目前我看到有两种选择: 将每个订单行发
我知道在 Groovy 中您可以使用字符串调用类/对象上的方法。例如: Foo."get"(1) /* or */ String meth = "get" Foo."$meth"(1) 有没有办法
在 ECMAScript6 中,您可以使用扩展运算符来解构这样的对象 const {a, ...rest} = obj; 它将 obj 浅拷贝到 rest,不带属性 a。 有没有一种干净的方法可以在
我有几个函数返回数字或None。我希望我的包装函数返回第一个不是 None 的结果。除了下面的方法之外,还有其他方法吗? def func1(): return None def func2(
假设我想设计一个 REST api 来讨论歌曲、专辑和艺术家(实际上我就是这样做的,就像我之前的 1312414 个人一样)。 歌曲资源始终与其所属专辑相关联。相反,专辑资源与其包含的所有歌曲相关联。
这是我认为必须经常出现的问题,但我一直无法找到一个好的解决方案。假设我有一个函数,它可以作为参数传递一个开放资源(如文件或数据库连接对象),或者需要自己创建一个。如果函数需要自己打开文件,最佳实践通常
我是一名优秀的程序员,十分优秀!