我有一个types.ts
定义一些类型的简单文件:
export interface MyInterface {
// ...
}
export const enum MyEnum {
// ...
}
export type MyType = {
// ...
}
Run Code Online (Sandbox Code Playgroud)
我看了一下新功能,import type
最新的打字稿这里。据我所知,它旨在解决从 .js 文件导入时似乎主要发生的特定问题。
我可以使用import
andimport type
语句导入我的类型。两者似乎工作得同样好。问题是我应该更愿意import type
更明确地帮助我避免一些理论上的边缘问题,还是我可以只是import
为了简单而使用并依赖于import elision
从编译的代码中删除这些问题?
换句话说:在这里使用有什么好处,import type
还是应该用于特定情况以解决import elision
缺点?
考虑以下代码:
#include <utility>
#include <string>
int bar() {
std::pair<int, std::string> p {
123, "Hey... no small-string optimization for me please!" };
return p.first;
}
Run Code Online (Sandbox Code Playgroud)
(简化感谢@ Jarod42 :-) ...)
我希望该功能可以简单地实现:
bar():
mov eax, 123
ret
Run Code Online (Sandbox Code Playgroud)
但是,实现调用operator new()
,std::string
用我的文字构造 an ,然后调用operator delete()
. 至少 - 这就是 gcc 9 和 clang 9 所做的(GodBolt)。这是铛的输出:
bar(): # @bar()
push rbx
sub rsp, 48
mov dword ptr [rsp + 8], 123
lea rax, [rsp + 32]
mov qword ptr [rsp …
Run Code Online (Sandbox Code Playgroud) 假设我的代码具有以下功能:
inline int foo() {
bar();
int y = baz();
return y;
}
Run Code Online (Sandbox Code Playgroud)
并假设bar()
和baz()
有副作用。
如果我写:
int z = foo();
printf("z is %d\n", z);
Run Code Online (Sandbox Code Playgroud)
那么显然都bar()
和baz()
必须执行。但如果我写:
foo();
Run Code Online (Sandbox Code Playgroud)
并且不使用返回值,调用的唯一原因baz()
是它的副作用。
有没有一种方法可以告诉我的编译器(对于:GCC、clang、MSVC、Intel 中的任何一个),例如“baz()
为了决定是否优化它,您可能会忽略它的副作用”?或者“为了决定是否优化它,您可能会忽略此指令的副作用”?
这个问题是针对 C 和 C++ 提出的,但可能与各种过程语言相关。让我们使用 C++,因为这是我现在最常用的。
笔记:
bar()
,baz()
不在我的控制之下。foo()
不得更改。当然baz()
,如果我愿意,我可以使用一些代理并懒惰地应用;或者只是为不使用的情况编写一个不同的函数y
。这不是我要问的。c++ side-effects compiler-optimization compiler-options elision
考虑以下代码:
#include <iostream>
struct M {
M() { std::cout << "M\n"; }
};
template <class T>
struct Test {
Test() { std::cout << "Test\n"; }
inline static auto m = M{};
};
int main() {
Test<int> t1;
//Test t;
//(void)&t1.m;
}
Run Code Online (Sandbox Code Playgroud)
使用最新的GCC或Clang打印出唯一的“测试”。但是,如果我们使用地址的m
(取消注释最后一行对象(void)&t1.m;
)或转换Test
类模板到常规(非模板)类则M
构造函数被调用。
C++ 标准允许这种行为吗?任何报价?
修改复制构造函数的“ explicit ”关键字可能会导致问题。\n作为函数参数传递的对象特别容易受到这些问题的影响。
\n这是我的代码:
\n#include <iostream>\n#include <string>\n\nclass Pig{\npublic:\n std::string _name;\npublic:\n Pig(std::string n) : _name(n) {}\n //~Pig() = default;\n explicit Pig(const Pig &other) {\n std::cout << "copy ctor!" << std::endl;\n this->_name = other._name;\n }\n};\n\nvoid show(Pig p) {\n std::cout << p._name << std::endl;\n}\n\nint main() {\n Pig pig{std::string("hello")};\n show(Pig{pig}); // no pass\n // show(Pig(pig)); // no pass\n return 0;\n}\n
Run Code Online (Sandbox Code Playgroud)\n编译器版本:g++(Ubuntu 9.4.0-1ubuntu1~20.04.1)9.4.0。
\n上面提到的代码不能用c++14 或更低版本编译,\n但用c++17 及更高版本编译成功。
\n这是编译器的错误:
\ntest.cpp: In function \xe2\x80\x98int main()\xe2\x80\x99:\ntest.cpp:22:7: error: cannot …
Run Code Online (Sandbox Code Playgroud) elision ×5
c++ ×4
copy-elision ×1
explicit ×1
import ×1
module ×1
side-effects ×1
stdstring ×1
typescript ×1