我有 C++ 背景,我完全理解并同意这个问题的答案:Why is “using namespace std;” 被认为是不好的做法?
所以我很惊讶,现在有了 C# 的一些经验,我看到了完全相反的情况:
using Some.Namespace;字面上到处都在使用。每当您开始使用类型时,首先为其命名空间添加 using 指令(如果它还没有的话)。我不记得看过一个.cs不以using System; using System.Collections.Generic; using X.Y.Z; etc.... 事实上,如果您通过 Visual Studio 向导添加一个新文件,它会自动在那里添加一些 using 指令,即使您可能根本不需要它们。因此,虽然在 C++ 社区中您基本上会受到私刑,但 C# 甚至鼓励这样做。至少在我看来是这样。
现在,我明白在 C# 和 C++ 中使用指令并不完全相同。另外,我确实明白,您可以using namespace在 C++ 中做的最讨厌的事情之一,即将它放在头文件中,由于缺乏头文件和#include.
然而,尽管存在差异,但在 C# 和 C++ 中使用指令的目的是相同的,只需一直输入SomeType,而不是更长的时间Some.Namespace.SomeType(在 C++ 中使用::而不是.)。出于同样的目的,对我来说,危险似乎也是一样的:命名冲突。
在最好的情况下,这会导致编译错误,因此您“只需”修复它。在最坏的情况下,它仍然可以编译,并且代码会默默地做与您预期不同的事情。所以我的问题是:为什么(显然)使用在 C# 和 C++ 中被认为如此糟糕的指令?
我对答案的一些想法(不过,这些都没有真正让我满意):
与 C++std相比,C# 中的命名空间往往更长,嵌套更多(vs. System.Collection.Generic)。因此,以这种方式对代码去噪有更多的愿望和更多的收获。但即使这是真的,这个论点也只适用于我们查看标准命名空间时。在 C# 和 …
在https://en.cppreference.com/w/cpp/utility/hash上,它说自从C++ 17开始
声明模板std :: hash的每个标准库头为std :: nullptr_t和所有cv-unqualified算术类型(包括任何扩展整数类型),所有枚举类型和所有指针类型提供std :: hash的启用特化.
因此,符合C++ 17的编译器应该编译这个小程序:
#include <functional>
int main()
{
std::hash<std::nullptr_t> h;
return h(nullptr);
}
Run Code Online (Sandbox Code Playgroud)
但是,GCC和Clang都报告了一个错误,说默认构造函数std::hash<std::nullptr_t>是(隐式)删除的.请看这里和这里自己验证.
Visual Studio会编译它.显然它会回来.0672807365
Q1: GCC和Clang是否仍然缺少这个C++ 17功能,因为诚然这不是一个高优先级的功能?或者我错过了什么?
Q2:我可以自己专注并像Visual Studio一样返回吗?一些其他价值,例如某些素数,不会更好地将它与其他哈希相结合吗?0672807365
由于我有限的汇编程序知识,我认为Visual Studio正在返回0.实际上,它正在返回672807365(值为eax).所以,我的第二个问题基本上是自己回答:我不会回到0我的专业领域来解决这个问题.
我正在将C ++ Visual Studio项目从VS2017迁移到VS2019。
我现在遇到一个错误,以前没有发生过,可以通过以下几行代码来重现:
struct Foo
{
Foo() = default;
int bar;
};
auto test = Foo { 0 };
Run Code Online (Sandbox Code Playgroud)
错误是
(6):错误C2440:“正在初始化”:无法从“初始化列表”转换为“ Foo”
(6):注意:没有构造函数可以采用源类型,或者构造函数重载解析度不明确
该项目用/std:c++latest标志编译。我把它复制在了哥德螺栓上。如果我将其切换到/std:c++17,它可以像以前一样正常编译。
我试图用clang编译相同的代码,-std=c++2a并得到了类似的错误。同样,默认或删除其他构造函数也会产生此错误。
显然,VS2019中添加了一些新的C ++ 20功能,我假设在https://en.cppreference.com/w/cpp/language/aggregate_initialization中描述了此问题的起源。在那里,它表示一个聚合可以是(除其他条件外)具有的结构
请注意,括号中的部分“明确允许使用默认或删除的构造函数”已删除,并且“用户提供”更改为“用户声明”。
因此,我的第一个问题是,我是否假设标准的这种更改是我的代码以前编译但现在不再编译的原因?
当然,解决此问题很容易:只需删除显式默认的构造函数即可。
但是,我已经在所有项目中明确地默认并删除了很多构造函数,因为我发现以这种方式使代码更具表现力是一个好习惯,因为与隐式默认或删除的构造函数相比,这样做只会带来更少的惊喜。但是,通过这种更改,这似乎不再是一个好习惯了...
所以我的实际问题是: 从C ++ 17到C ++ 20的变化背后的原因是什么?向后兼容的突破是故意的吗?是否有一些折衷办法,例如“确定,我们在这里破坏了向后兼容性,但这是为了更大的利益。”吗?这个更大的好处是什么?
在研究此问题的答案的过程中,我发现(以前不知道)gcc和clang char如果声明了数组,则它们可以作为模板参数static。例如,此代码使用gcc和clang进行编译:
#include <type_traits>
template <int N, const char (&string)[N]>
auto foo()
{
if constexpr (string[0] == 'i')
return 0;
else
return 3.14f;
}
void bar()
{
static constexpr char string1[] = "int";
static constexpr char string2[] = "float";
auto i = foo<sizeof(string1), string1>();
auto f = foo<sizeof(string2), string2>();
static_assert(std::is_same_v<decltype(i), int>);
static_assert(std::is_same_v<decltype(f), float>);
}
Run Code Online (Sandbox Code Playgroud)
MSVC也允许这样做。但是,要使其与MSVC一起使用,我必须在全局名称空间中声明两个字符串。然后它也一样有效。
所以我的问题是:标准对此有何表述?哪个编译器(如果有)是正确的?
考虑一下我在这个问题中发现的这个功能:
void to_bytes(uint64_t const& x, uint8_t* dest) {
dest[7] = uint8_t(x >> 8*7);
dest[6] = uint8_t(x >> 8*6);
dest[5] = uint8_t(x >> 8*5);
dest[4] = uint8_t(x >> 8*4);
dest[3] = uint8_t(x >> 8*3);
dest[2] = uint8_t(x >> 8*2);
dest[1] = uint8_t(x >> 8*1);
dest[0] = uint8_t(x >> 8*0);
}
Run Code Online (Sandbox Code Playgroud)
由于x并且dest可能指向同一内存,因此不允许编译器将其优化为单个qword移动(每行可能会更改的值x)。
到目前为止,一切都很好。
但是,如果您x按值传递,则此参数不再成立。实际上,GCC可以mov按照预期将其优化为一条简单的指令:https : //godbolt.org/z/iYj1or
但是,c不会:https : //godbolt.org/z/Hgg5z9
我假设,由于甚至不能保证完全x占用任何堆栈内存,因此在调用该函数之前进行任何dest指向操作的尝试都将导致未定义的行为,因此编译器可以假定这种情况永远不会发生。那意味着c在这里失去了一些机会。但是我不确定。有人可以澄清吗?x
如何通过使用pandas或numpy将一列6个整数数字分成6列,每列一个数字?
import pandas as pd
import numpy as np
df = pd.Series(range(123456,123465))
df = pd.DataFrame(df)
df.head()
Run Code Online (Sandbox Code Playgroud)
Number
654321
223344
Run Code Online (Sandbox Code Playgroud)
Number | x1 | x2 | x3 | x4 | x5 | x6 |
654321 | 6 | 5 | 4 | 3 | 2 | 1 |
223344 | 2 | 2 | 3 | 3 | 4 | 4 |
Run Code Online (Sandbox Code Playgroud) 在JDBC 文档setObject中我发现了这样一句话:
JDBC 规范指定了从 Java 对象类型到 SQL 类型的标准映射。
但是,我找不到定义此映射的位置。我找到的就是这个。但这仅指定 SQL 类型和 JDBC 类型之间的映射。但我不明白如何从 JDBC 类型转换为 Java 类型。
更具体地说,我想知道这段代码是否保证永远不会抛出InvalidCastException:
int type = resultSet.getMetadata().getColumnType(1);
if (type == Types.LONGNVARCHAR || type == Types.CHAR) {
String abc = (String)resultSet.getObject(1);
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,它是人们所期望的非常直观的String,但还有许多其他 SQL 类型我没有这样的直觉。
我只是找不到一个表格来告诉我可以根据常量的知识安全地执行哪些转换java.sql.Types。
在生产代码中,我在.cpp文件中找到了它:
namespace
{
void foo(); // declared in anonymous namespace, defined below
}
void bar() // declared in corresponding .h file, defined here
{
::foo(); // call foo
}
void ::foo() // intended to refer to the anonymous foo above
{
}
Run Code Online (Sandbox Code Playgroud)
我们使用的是Visual Studio2017。我偶然发现了这一点,因为intellisense给了我一个警告,警告foo它找不到函数定义。但是,它可以编译和链接而不会出错,并且代码可以执行预期的工作。
我把它弄错了,发现gcc和clang拒绝此代码,原因与intellisense给我警告的原因相同。
所以我的问题是:哪个编译器正确,为什么?
此外,出于兴趣,我向foo全局名称空间添加了另一个声明,如下所示:
namespace
{
void foo();
}
void foo(); // another declaration
void bar()
{
::foo(); // which foo will be called?
}
void ::foo() // which foo will be …Run Code Online (Sandbox Code Playgroud)