gpt4 book ai didi

c++ - 第一次分配后如何更改const std::shared_ptr?

转载 作者:行者123 更新时间:2023-11-27 23:52:53 26 4
gpt4 key购买 nike

如果我定义了相同类型的shared_ptrconst shared_ptr,如下所示:

std::shared_ptr<int> first = std::shared_ptr<int>(new int);
const std::shared_ptr<int> second = std::shared_ptr<int>();


然后尝试像这样更改 const shared_ptr的值:

second = first;


它会导致编译错误(应该如此)。但是,即使我尝试放弃const部分:

(std::shared_ptr<int>)second = first;


上面代码的结果是, second最终为空,而未触摸 first(例如,引用计数仍为1)。

最初设置后,如何更改 const shared_ptr的值?使用std的指针甚至可能吗?

谢谢!

最佳答案

在其构造或销毁范围之外以任何方式修改声明为const的变量都是未定义的行为。

const std::shared_ptr<int> second


这是一个声明为 const的变量。

在构建之后和销毁之前,没有符合标准的方法来更改它所指的内容。

话虽如此,我不确定在同一位置手动调用析构函数并构造一个新的 shared_ptr可能是合法的。您绝对不能用其原始名称来引用所说的 shared_ptr,并且可能离开原始 shared_ptr的范围是非法的(因为析构函数试图破坏原始对象,编译器可以证明它是一个空的共享指针(或非空)),具体取决于 const对象的构造方式)。

即使您可以提出标准允许的参数,这也是一个坏主意。

const对象不能更改。

...

您对 shared_ptr<int>的转换只是创建一个临时副本。然后分配给它,并更改临时副本。然后,该临时副本将被丢弃。未修改 const shared_ptr<int>是预期的行为。分配临时副本的合法性是因为 shared_ptr和大多数 std库是在我们能够根据左侧的r / lvalue-ness重载 operator=之前设计的。

...

现在,为什么会这样呢?编译器使用实际的 const ness作为优化提示。

{
const std::shared_ptr<int> bob = std::make_shared<int>();
}


在上述情况下,编译器可以肯定地知道 bob在作用域的末尾是非空的。无法对 bob做任何事情,这可能会使它变成空的并且仍然让您拥有定义的行为。

因此,当销毁检查指针是否为空的 bob时,编译器可以消除作用域末尾的分支。

如果将 bob传递给检查 inline的空状态的 bob函数,则可能会发生类似的优化。编译器可以省略检查。

假设您将bob传递给

void secret_code( std::shared_ptr<int> const& );


编译器无法查看 secret_code的实现。可以假定密码不会编辑bob。

如果未将其声明为 const,则 secret_code可以合法地对该参数进行 const_cast<std::shared_ptr&>并将其设置为null。但是如果 secret_code的参数实际上是 const,则这是未定义的行为。 (任何强制转换为const的代码都负责保证这样做不会导致对实际 const值的任何实际修改)

如果在 const上没有 bob,则编译器无法保证:

{
const std::shared_ptr<int> bob = std::make_shared<int>();
secret_code(bob);
if (bob) {
std::cout << "guaranteed to run"
}
}


guaranteed to run字符串将被打印。

const上使用 bob时,编译器可以自由地消除上面的 if检查。

...

现在,不要混淆我的解释,为什么标准不能用“如果不发生就没有问题”来编辑 const堆栈变量。标准规定您不得这样做;如果这样做,后果将是无限的,并且可能随编译器的新版本一起增长。

...

来自评论:


  对于反序列化过程,实际上是从文件反序列化对象的一种构造方法。 C ++很不错,但是它有其缺点,有时可以搜索较少的正统方法。


如果是构造函数,则使其成为构造函数。

在C ++ 17中,返回 T的函数在很多方面与真实构造函数具有相同的地位(由于保证省略)。在C ++ 14中,情况并非如此(您还需要一个move构造函数,并且编译器需要将其移出)。

因此,C ++中类型为 T的反序列化构造函数需要返回 T,它不能接受 T的引用,并且不能成为真正的构造函数。

编写此文件有些麻烦,但是可以做到。使用相同的代码进行序列化和反序列化更让人痛苦(我无法马上弄清楚如何实现)。

关于c++ - 第一次分配后如何更改const std::shared_ptr?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45018823/

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