暗示 return 值不打算存储的方法
Ways to imply return values are not meant to be stored
我们可以使用 nodiscard
属性来暗示不应丢弃函数的 return 值。是否有任何属性(或其他方式)暗示某些 opposite 语义:函数的 return 值只能临时使用(“临时”我的意思是,不分配给除本地变量之外的任何变量)?
由于目的可能不是很清楚,假设我有一个 class FooHolder
来保存资源 Foo
;调用 FooHolder::getFoo()
return 的 Foo
它 目前 持有:
#include <memory>
class Foo {
public:
Foo& bar() { /* do something */ return *this; }
const Foo& far() const { /* do something else */ return *this; }
};
class FooHolder {
private:
std::shared_ptr<Foo> _foo { nullptr };
public:
FooHolder(): _foo(std::make_shared<Foo>()) {}
Foo& getFoo() { return *_foo; }
const Foo& getFoo() const { return *_foo; }
};
而且我们可以在很多方面使用它:
// Others may try storing some status:
Foo* g_foo = nullptr;
int main() {
FooHolder foo_holder {};
// I want to support this:
foo_holder.getFoo().bar().far() /* chained calls... */ ;
// Also, maybe this:
auto& local_foo = foo_holder.getFoo();
local_foo.bar();
local_foo.far();
// But not this, because the Foo instance that FooHolder holds may perish:
static Foo& static_foo = foo_holder.getFoo();
// Nor this:
g_foo = &local_foo;
return 0;
}
那么有没有办法阻止(或至少警告)存储 FooHolder::getFoo()
的 return 值?或者,通过引用 return 资源是不好的做法吗?
[...] is it bad practice to return resources by reference?
视情况而定。 return non-const 引用的方法示例很多,它们都很好。例如考虑标准容器元素访问器。但是,它们并不意味着封装。 std::vector::operator[]
并不意味着对调用者隐藏元素,它意味着提供对它的直接访问。返回一个 non-const 引用不是封装!恰恰相反。请注意 std::vector
甚至授予您访问其 data()
的权限。那也不是封装,它依赖于用户不要 delete[] some_vect.data()
或做其他会破坏向量的错误事情。
您希望FooHolder
封装包含的Foo
。
这是相反的要求。
你基本上有两个选择:A) 呼叫者知道他们在做什么。他们阅读文档。他们知道他们不应该以错误的方式使用 FooHolder::getFoo
。 B)使用适当的封装:永远不要让调用者直接访问 non-const Foo
:
class FooHolder {
private:
std::shared_ptr<Foo> _foo { nullptr };
public:
FooHolder(): _foo(std::make_shared<Foo>()) {}
// nope // Foo& getFoo() { return *_foo; }
// maybe // const Foo& getFoo() const { return *_foo; }
FooHolder& bar() {
_foo->bar();
return *this;
}
// ..same for far() ...
};
请注意,A) 是一个可行的解决方案。考虑到像 std::shared_ptr
这样的东西也可能被严重错误地使用。用户应该知道如何正确使用它。不同之处在于 std::shared_ptr
是一个标准类型,带有大量文档。因此,如果这是要走的路,您应该三思。
So are there ways to prevent (or at least warn about) storing the return value of FooHolder::getFoo()?
没有。一旦您 return 编辑了 non-const 参考资料,所有赌注都将取消。 FooHolder
不再控制调用者可以对该引用执行的操作。您可以阻止复制或移动,但不能阻止引用。
我们可以使用 nodiscard
属性来暗示不应丢弃函数的 return 值。是否有任何属性(或其他方式)暗示某些 opposite 语义:函数的 return 值只能临时使用(“临时”我的意思是,不分配给除本地变量之外的任何变量)?
由于目的可能不是很清楚,假设我有一个 class FooHolder
来保存资源 Foo
;调用 FooHolder::getFoo()
return 的 Foo
它 目前 持有:
#include <memory>
class Foo {
public:
Foo& bar() { /* do something */ return *this; }
const Foo& far() const { /* do something else */ return *this; }
};
class FooHolder {
private:
std::shared_ptr<Foo> _foo { nullptr };
public:
FooHolder(): _foo(std::make_shared<Foo>()) {}
Foo& getFoo() { return *_foo; }
const Foo& getFoo() const { return *_foo; }
};
而且我们可以在很多方面使用它:
// Others may try storing some status:
Foo* g_foo = nullptr;
int main() {
FooHolder foo_holder {};
// I want to support this:
foo_holder.getFoo().bar().far() /* chained calls... */ ;
// Also, maybe this:
auto& local_foo = foo_holder.getFoo();
local_foo.bar();
local_foo.far();
// But not this, because the Foo instance that FooHolder holds may perish:
static Foo& static_foo = foo_holder.getFoo();
// Nor this:
g_foo = &local_foo;
return 0;
}
那么有没有办法阻止(或至少警告)存储 FooHolder::getFoo()
的 return 值?或者,通过引用 return 资源是不好的做法吗?
[...] is it bad practice to return resources by reference?
视情况而定。 return non-const 引用的方法示例很多,它们都很好。例如考虑标准容器元素访问器。但是,它们并不意味着封装。 std::vector::operator[]
并不意味着对调用者隐藏元素,它意味着提供对它的直接访问。返回一个 non-const 引用不是封装!恰恰相反。请注意 std::vector
甚至授予您访问其 data()
的权限。那也不是封装,它依赖于用户不要 delete[] some_vect.data()
或做其他会破坏向量的错误事情。
您希望FooHolder
封装包含的Foo
。
这是相反的要求。
你基本上有两个选择:A) 呼叫者知道他们在做什么。他们阅读文档。他们知道他们不应该以错误的方式使用 FooHolder::getFoo
。 B)使用适当的封装:永远不要让调用者直接访问 non-const Foo
:
class FooHolder {
private:
std::shared_ptr<Foo> _foo { nullptr };
public:
FooHolder(): _foo(std::make_shared<Foo>()) {}
// nope // Foo& getFoo() { return *_foo; }
// maybe // const Foo& getFoo() const { return *_foo; }
FooHolder& bar() {
_foo->bar();
return *this;
}
// ..same for far() ...
};
请注意,A) 是一个可行的解决方案。考虑到像 std::shared_ptr
这样的东西也可能被严重错误地使用。用户应该知道如何正确使用它。不同之处在于 std::shared_ptr
是一个标准类型,带有大量文档。因此,如果这是要走的路,您应该三思。
So are there ways to prevent (or at least warn about) storing the return value of FooHolder::getFoo()?
没有。一旦您 return 编辑了 non-const 参考资料,所有赌注都将取消。 FooHolder
不再控制调用者可以对该引用执行的操作。您可以阻止复制或移动,但不能阻止引用。