从C++20开始,[[nodiscard]]
就可以应用于构造函数。http://wg21.link/p1771的例子如下:
struct [[nodiscard]] my_scopeguard { /* ... */ };
struct my_unique {
my_unique() = default; // does not acquire resource
[[nodiscard]] my_unique(int fd) { /* ... */ } // acquires resource
~my_unique() noexcept { /* ... */ } // releases resource, if any
/* ... */
};
struct [[nodiscard]] error_info { /* ... */ };
error_info enable_missile_safety_mode();
void launch_missiles();
void test_missiles() {
my_scopeguard(); // warning encouraged
(void)my_scopeguard(), // warning not encouraged, cast to void
launch_missiles(); // comma operator, statement continues
my_unique(42); // warning encouraged
my_unique(); // warning not encouraged
enable_missile_safety_mode(); // warning encouraged
launch_missiles();
}
error_info &foo();
void f() { foo(); } // warning not encouraged: not a nodiscard call, because neither
// the (reference) return type nor the function is declared nodiscard
通常构造函数没有副作用。因此丢弃结果是没有意义的。例如,如下所示丢弃std::vector
是没有意义的:
std::vector{1,0,1,0,1,1,0,0};
如果std::vector
构造函数为[[nodiscard]]
,则会很有用,因此上面的代码会产生一个警告。
有副作用的构造函数是锁构造函数,如unique_lock
或lock_guard
。但这些构造函数也是标记为[[nodiscard]]
的好对象,以避免丢失作用域,如下所示:
std::lock_guard{Mutex};
InterThreadVariable = value; // ouch, not protected by mutex
如果std::lock_guard
构造函数为[[nodiscard]]
,则会很有用,因此上面的代码会产生一个警告。
当然,也有像return std::lock_guard{Mutex}, InterThreadVariable;
这样的情况,但是仍然有[[nodiscard]]
保护并像return ((void)std::lock_guard{Mutex}, InterThreadVariable);
那样在本地抑制它们的情况非常罕见
那么,有没有什么情况下构造函数 * 不 * 应该是nodiscard?
2条答案
按热度按时间cygmwpex1#
pybind11
库中的示例:要为python Package 一个C++类,您需要:qaxu7uf22#
如果构造函数没有副作用,那么在我看来就不值得这么做,代码也很混乱。您很快就会注意到,在示例中您忘记了为该向量命名。
对于少数有副作用的构造函数,现在有
[[nodiscard]]
可用。(这很好)因为你的问题是为什么不改变默认值并用
[[may_discard]]
标记例外情况(基本上C的定义似乎到处都是错误的默认值),这将是向后兼容性。这样的中断通常只在极少数情况下被接受,即现有的东西是有害的,并且如果有替代品的话。(想到了std::auto_ptr
的反对意见)现在有一些新的方法来解决这个问题。一个例子是Herb Sutter的个人实验cppfront。它定义了一种新的语法,可以正确地获取所有默认值,并将其转换为常规的C,然后进行编译。你可以查看他在CppCon 2022的主题演讲,他在演讲中演示了这一点:Can C++ be 10x Simpler & Safer?