假设我有一个简单的Duration
类:
class Duration
{
int seconds;
public:
Duration(int t_seconds) : seconds(t_seconds) { }
};
int main()
{
Duration t(30);
t = 60;
}
Run Code Online (Sandbox Code Playgroud)
我决定我不喜欢能够从 隐式转换int
为Duration
。我可以制作构造函数explicit
:
class Duration
{
int seconds;
public:
explicit Duration(int t_seconds) : seconds(t_seconds) { }
};
int main()
{
Duration t(30); // This is fine, conversion is explicit
t = 60; // Doesn't compile: implicit conversion no longer present for operator=
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我不想立即破坏所有隐式转换为 的调用代码怎么办Duration
?我想要的是这样的:
class Duration
{ …
Run Code Online (Sandbox Code Playgroud) 在 Visual Studio 中,警告 C4996(使用不推荐使用的函数)被视为错误,使用不推荐使用的函数的代码根本不会编译。
有多种方法可以完全禁用 C4996,可以为单行、翻译单元或整个项目禁用它。但是如果我希望它仍然发出警告,但允许编译而不将其视为错误怎么办?
#include <iostream>
[[deprecated]]
void deprecated_function()
{
std::cout << "I function, but have been deprecated.\n";
}
int main() {
deprecated_function();
}
Run Code Online (Sandbox Code Playgroud)
这根本无法编译。
#include <iostream>
[[deprecated]]
void deprecated_function()
{
std::cout << "I function, but have been deprecated.\n";
}
int main() {
#pragma warning(suppress: 4996)
deprecated_function();
}
Run Code Online (Sandbox Code Playgroud)
这会编译,但根本不会发出警告。
对于已弃用的函数,是否可以告诉 Visual Studio 发出警告,但仍允许编译?我正在考虑重构目的,我想将一个函数标记为已弃用,标识它使用的所有位置,但代码仍在每个中间阶段编译,其中一些但不是所有已弃用函数的用途已被替换。
我正在使用 Visual Studio 2019 Community 16.8.4 进行编译,警告级别设置为 /W3,“将警告视为错误”设置为“否”。如果发出此特定警告,它似乎被视为错误。
对于无作用域枚举,答案是“大多数”,因为隐式转换为基础整数类型。但是,作用域枚举没有这种隐式转换。相反,为它们定义了一些但不是所有可用于无作用域枚举的运算符。
#include <iostream>
enum class Color{
Red,
Green,
Blue
};
int main()
{
std::cout << (Color::Red < Color::Green) << '\n';
// Fine, operator< is defined for Color
std::cout << (Color::Red + Color::Green == Color::Green) << '\n';
// no match for 'operator+'
}
Run Code Online (Sandbox Code Playgroud)
我的猜测是关系运算符已定义,但算术运算符未定义,但我在 cppreference 页面上没有看到任何明确说明的内容,也没有进行实际的标准潜水以了解 C++ 对事情。
激励示例:
假设我们有一个类Foo
和一个ObservesFoo
具有指向 a 实例的非拥有指针的类Foo
。我们可以这样写:
class Foo {};
class ObservesFoo
{
Foo* p_foo = nullptr;
ObservesFoo(Foo* t_foo) : p_foo(t_foo) { }
};
Run Code Online (Sandbox Code Playgroud)
但也许我不认为nullptr
这是一个有效的价值p_foo
。我可以编写一个不同的构造函数来ObservesFoo
强制执行此要求,而无需执行诸如 throw if t_foo
is invalid 之类的操作:
ObservesFoo(Foo& t_foo) : p_foo(&t_foo) { }
Run Code Online (Sandbox Code Playgroud)
然后我对自己说,“等等,这个构造函数没有改变 t_foo
。我不应该把它当作一个const Foo&
吗?” 但是,如果我这样编写函数,它可能会接受一个临时Foo
参数作为其参数,一旦构造函数返回,其生命周期将立即结束,这将消除我从确保p_foo
不是的任何保证nullptr
,因为现在它可以非常很容易成为悬垂的指针。
有没有一种干净的方法可以在Foo&
构造函数和const Foo&
构造函数之间取得中间立场?
考虑:
#include <iostream>
#include <iomanip>
int main()
{
std::cout << std::fixed << std::setprecision(2);
std::cout << 0.125 << '\n'; // Prints "0.12"
std::cout << 0.126 << '\n'; // Prints "0.13" as expected
}
Run Code Online (Sandbox Code Playgroud)
我知道浮点数学并不完全精确,但0.125
实际上不是准确表示的值之一吗?为什么格式化时是"0.12"
向下舍入而不是向上舍入?"0.13"
考虑以下:
#include <iostream>
#include <variant>
int main ()
{
std::variant<int, float> foo = 3;
if(foo == 3)
{
std::cout << "Equals 3\n";
}
}
Run Code Online (Sandbox Code Playgroud)
这不会编译,因为foo == 3
:
<source>:7:12: error: no match for 'operator==' (operand types are 'std::variant<int, float>' and 'int')
7 | if(foo == 3)
| ~~~ ^~ ~
| | |
| | int
| std::variant<int, float>
In file included from /opt/compiler-explorer/gcc-12.1.0/include/c++/12.1.0/iosfwd:40,
from /opt/compiler-explorer/gcc-12.1.0/include/c++/12.1.0/ios:38,
from /opt/compiler-explorer/gcc-12.1.0/include/c++/12.1.0/ostream:38,
from /opt/compiler-explorer/gcc-12.1.0/include/c++/12.1.0/iostream:39,
from <source>:1:
/opt/compiler-explorer/gcc-12.1.0/include/c++/12.1.0/bits/postypes.h:192:5: note: candidate: 'template<class _StateT> …
Run Code Online (Sandbox Code Playgroud) 我正在尝试将 a 复制到usingstd::array
中。std::vector
std::copy
根据cppReference,其原型std::copy
为:
std::copy(InputIt first, InputIt last, OutputIt d_first)
Run Code Online (Sandbox Code Playgroud)
,其中OutputIt d_first
代表目标范围的开头。
通过遵循实现,我有以下代码:
std::array<int, 10> arr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
std::vector<int> vec;
std::copy(arr.begin(), arr.end(), vec.begin());
Run Code Online (Sandbox Code Playgroud)
然而,代码并没有像我预期的那样工作,它只是没有将 复制array
到vector
.
根据快速谷歌搜索,代码应该是:
std::array<int, 10> arr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
std::vector<int> vec;
std::copy(arr.begin(), arr.end(), std::back_inserter(vec));
Run Code Online (Sandbox Code Playgroud)
我的问题是,为什么第一个代码不起作用?
不vec.begin()
被视为OutputIt d_first
,其中我的理解是“代表目的地第一个位置的迭代器”?
c++ ×7
arrays ×1
containers ×1
enums ×1
operators ×1
reference ×1
variant ×1
vector ×1
visual-c++ ×1