下面的 C++ 代码格式正确吗?std::string函数执行完成之前还是之后会被销毁?
void my_function(const char*);
...
my_function(std::string("Something").c_str());
Run Code Online (Sandbox Code Playgroud)
我知道我可以做到my_function("Something"),但我用std::string这种方式来说明我的观点。
我想交换两个固定大小的整数数组。
与直觉相反,以下内容无法编译,因为没有swap找到匹配的实例。
#include <array>
#include <utility>
int main()
{
std::array<int,3> a, b;
std::swap< std::array<int,3> >( a, b );
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我觉得这很令人惊讶。但是,用编译替换交换std::swap(a,b)并且(根据 VSCode)具有签名
inline void std::swap<int, 3UL>(std::array<int, 3UL> &__one, std::array<int, 3UL> &__two)
Run Code Online (Sandbox Code Playgroud)
我也无法理解。
问:这是怎么回事?
有人能解释一下这段代码的执行顺序吗?
struct Foo {
~Foo() {
std::cout << "1";
}
};
Run Code Online (Sandbox Code Playgroud)
int main() {
const Foo& bar = Foo();
const Foo& baz = std::move(Foo());
std::cout << "2";
}
Run Code Online (Sandbox Code Playgroud)
以下代码打印121.
我明白为什么我在 2 之后得到 1,这是因为对象的生命周期绑定到它执行的代码块,而且我也知道右值可以绑定到左值 const 引用,但是为什么立即调用移动对象的析构函数?这是什么原因呢?这个析构函数到底在哪里被调用?
给定基类 A 和派生类 B,A 删除了移动构造函数:
class A {
public:
A() {}
A(const A&) = default;
A(A&&) = delete;
};
class B : public A
{
};
Run Code Online (Sandbox Code Playgroud)
在这种情况下,由于删除了移动构造函数,以下函数无法编译:
A f() {
A a;
return a;
}
Run Code Online (Sandbox Code Playgroud)
但 B 的类似函数不会报告任何错误:
B g() {
B b;
return b;
}
Run Code Online (Sandbox Code Playgroud)
这是否意味着B中的移动构造函数没有被删除?我想知道标准中的规则是什么。
std::format有一个(编译时和运行时)格式字符串验证,但此验证中不包括的一件事是是否有足够的{}占位符用于所有参数(过多的参数将被默默忽略)。
我认为这在某些罕见的情况下可能很有用(例如,如果您生成格式字符串),但我不需要它,并且因此我遇到了一些错误。
我可以做些什么来检查这个编译时间吗?可能通过包装std::format我自己的函数。
例子:
#include <format>
#include <iostream>
int main()
{
std::cout << std::format("{} {}", 1, 2, 3, 4, 5) << '\n'; // Prints `1 2`, no error!
}
Run Code Online (Sandbox Code Playgroud)
注意: std::format 确实有编译时格式字符串验证。他们只是不检查这个具体问题(过多的争论)。
我正在编译时使用计算一些数据std::vector,并希望将结果作为数组返回,以便可以在运行时进一步使用。我在不进行两次计算的情况下设置数组大小时遇到问题。
这是我迄今为止所做的事情的简化示例。代码按预期编译并运行。
constexpr auto make_vector() {
// complex calculation here
return std::vector{1, 2, 3};
}
constexpr auto make_array() {
const auto vec = make_vector();
std::array<int, make_vector().size()> result{};
std::copy(vec.cbegin(), vec.cend(), result.begin());
return result;
}
int main() {
constexpr auto result = make_array(); // std::array<int, 3>{1, 2, 3}
}
Run Code Online (Sandbox Code Playgroud)
我理解为什么不能用于vec.size()数组大小以及为什么make_vector().size()会产生编译时常量。做两次似乎不是正确的方法。
有没有办法避免调用make_vector两次?我在这里错过了一个基本概念吗?
以下代码打印nullptr而不是empty(godbolt 链接):
#include <iostream>
class empty { };
#if 1
void f(std::nullptr_t) {
std::cout << "nullptr\n";
}
#endif
void f(empty) {
std::cout << "empty\n";
}
int main() {
f({});
}
Run Code Online (Sandbox Code Playgroud)
禁用f(nullptr_t)变体会导致empty打印。当两个变体都可用时,C++ 使用什么规则来选择nullptr_t变体?empty
C++23 允许[[...]]lambda 表达式中的属性:
auto lambda = [] [[nodiscard]]
{
return 42;
};
Run Code Online (Sandbox Code Playgroud)
但是语法有两个属性列表,大致在参数列表之前和之后:
auto lambda = [] [[nodiscard]] () [[deprecated]]
// (1)~~~~~~~~~~ (2)~~~~~~~~~~~ // (2) seems to have no effect here
{
return 42;
};
Run Code Online (Sandbox Code Playgroud)
这两个列表适用于不同的事物,但我无法弄清楚第二个列表的用途,以及我可以在此处放置哪些属性。对于我在 (2) 中尝试的任何属性,Clang 警告:'...' attribute cannot be applied to types。
标准是这样说的:
... attribute-specifier-seq [位于位置 (2)] 属于相应函数调用运算符或运算符模板的类型。
attribute-specifier-seq [位于位置 (1)] 属于相应的函数调用运算符或运算符模板。
“属于相应函数调用运算符的类型”让我感到困惑。我可以在这里放置哪些属性?这是否仅适用于特定于编译器的属性?如果是,这里可以使用哪些非标准属性?
显然,列表 (2) 早在 C++23 之前就已存在(该提案添加了列表 (1))。
我无法理解requires关键字如何在嵌套模板中工作。
下面的代码可以在最新版本的 MSVC 和 gcc 上编译(分别使用/std:c++latest和)。-std=c++2a
requires在这样的场景中是否会被简单地丢弃?我不应该这样使用它吗?
#include <type_traits>
template <
template < typename >
requires (false) // Should not this stop compilation?
typename Wrapper >
using Test = Wrapper < int >;
template < typename >
struct S
{
};
int main() {
Test < S > var;
return 0;
}
Run Code Online (Sandbox Code Playgroud)