gpt4 book ai didi

c++ - 如何正确组合可变对象 const

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:20:28 27 4
gpt4 key购买 nike

如果您尝试传递对临时对象的引用,则需要

const:

http://msdn.microsoft.com/query/dev12.query?appId=Dev12IDEF1&l=EN-US&k=k%28C4239%29;k%28vs.output%29&rd=true

这意味着在 C++ 中不可能将对象的可修改包装器建模为临时对象(无需强制使对象成为左值):

inline char * PcToUnix(AutoCStringBufferA & buffer) { return PcToUnix(buffer, buffer.size()); }
inline char * PcToUnix(CStringA & str) { return PcToUnix(make_autobuffer(str)); }

PcToUnix :将字符缓冲区从 CR+LF 原位转换为 CR。make_autobuffer :获取一个 CString,并锁定其底层字符缓冲区,以便我们可以在 autobuffer 的生命周期内直接访问以对其进行操作。

所以我不能编写一个调用语句来获取底层字符串,将其包装在缓冲区管理对象(可变)中,将其传递给操作缓冲区内容的函数,然后返回,除非 autobuffer 声明为作为 const & 传递:

错误:

inline char * PcToUnix(AutoCStringBufferA & buffer) { return PcToUnix(buffer, buffer.size()); }

好吗?!

inline char * PcToUnix(const AutoCStringBufferA & buffer) { return PcToUnix(buffer, buffer.size()); }

但是“正确”的形式似乎指定了一个契约(Contract):“我不会修改你的缓冲区”。这里的 constness 在 autobuffer 对象级别在逻辑上是正确的 - 它在 PcToUnix() 期间没有被修改 - 缓冲区包装器对象本身(即 autobuffer)在 PcToUnix 期间未修改 - 所以它确实是 const...

但是,但是,它正在修改其底层对象 - 根据定义 - 其他东西的包装器 - 并且其他东西已被修改。

在我看来,这似乎是 C++ const 的一个根本缺陷。没有办法同时满足当前规则(不使用非标准编译器行为或编写误导性 API 契约(Contract)或编写不必要的冗长代码。

详细方法:

inline char * PcToUnix(CStringA & str) { auto adapter = make_autobuffer(str); return PcToUnix(adapter); }

误导性的 API 方法:

inline char * PcToUnix(const AutoCStringBufferA & buffer) { return PcToUnix(buffer, buffer.size()); }
inline char * PcToUnix(CStringA & str) { return PcToUnix(make_autobuffer(str)); }

如果 C++ 提供了一种方法来指定包装器的常量性与被包装对象的常量性分开,那么我们就有了一种合理的方法来创建规则并简洁地表达 API。但我只是不知道如何实现这一目标。

预智能指针(或对于没有包装层的所有上下文)可以从底层对象的常量中单独指定指针的常量:

T * const pConstPointerToMutableObject;
const T * pMutablePointerToConstObject;
const T * const pConstPointerToConstObject;

但是对于包装器对象没有任何相应的支持。没有办法将 referer 的常量与 refere 的常量分开表达。也没有任何一套合理的规则来定义或控制 const 的交换/关联/分配性质。

我不明白为什么没有经常提出这个问题。我经常偶然发现这一点,并发现 const 是一个巨大的 PIA,因为它 .

理想情况下,代码应该是简单可堆肥的——即一个人应该能够在另一层包装一些更简单的对象,以某种方式适应它——可能过滤访问,或者添加关于管理子对象的智能,或者底层事物的延迟实例化,等等,这样就可以建立复杂和特定的数据接口(interface),而不必一遍又一遍地重新设计基本对象——只需包裹在一两层中,为上下文添加必要的智能/逻辑/接口(interface)/适应这是需要的。

但由于常量正确性问题,C++ 使这几乎不可能。 (或者,我太愚蠢了,无法弄清楚如何做所有这些,并且在我广泛的阅读中,我已经设法想念它是如何完成的,甚至没有人在讨论这些问题而只是掩盖并忽略 const 的这一方面)。也许 SO 上的某个人可以纠正我的错误,无论我犯了什么错误??

最佳答案

const 正确性的简单方法:使用可传递的 const。

看来您对免费语言级别的要求有点过分了。实际上,它的设计(除其他事项外)是为了让您为使用的东西付费,并确保安全和高效。是的,它可能非常冗长。

就物理常量感知的容器而言,C++ 当然能够支持这种区别;例如:

void A(const std::shared_ptr<const bool>& p) { /* ... */}
void B(const std::shared_ptr<bool>& p) { /* ... */}

void C() {
A(std::make_shared<bool>(false)); // << ok
A(std::make_shared<const bool>(false)); // << ok

B(std::make_shared<bool>(false)); // << ok
B(std::make_shared<const bool>(false)); // << error. API forbids removal of const.
}

但 C++ 标准库并未提供您可能需要的所有容器来完成您的要求。

列举您需要的智能指针变体,并考虑它们负责对象的生命周期和从一个容器到另一个容器的转换。另请注意,如果您仅支持传递常量,该列表会缩短多少。然后考虑 OP 中的 API 通常会转换为模板以轻松支持变体。

有时,您必须处理接口(interface)不太理想的类型。在这些情况下,为它们创建一个容器并引入您理想的 const 形式通常是最简单的。

使用这种方法,容器完成了大部分繁重的工作(=让您免于在调用站点的冗长)。

当然,进行字符串转换的 C++ 风格看起来更像是:

std::string PCToUnix(std::string pString) {
...mutate pString...
return pString;
}

或就地:

void PCToUnix(std::string& pString) {
...mutate pString...
}

关于c++ - 如何正确组合可变对象 const,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27066943/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com