不行,因为模板代码是每个模块单独生成的。所以,当你的EXE实例化一个std::string并将其传递给DLL时,DLL将开始在其上使用完全不同的实现。结果是一团糟,但它通常会有点工作,因为实现非常相似,或者这种混乱很难检测,因为它是某种微妙的堆损坏。即使它们都使用相同版本的VS构建,也非常不稳定/脆弱,我不建议这样做。要么在模块之间使用C风格接口(例如COM),要么就不要使用DLL。更详细的解释在这里:Creating c++ DLL without static methods 和这里:How can I call a function of a C++ DLL that accepts a parameter of type stringstream from C#?
通常情况下,您不能混合使用由不同编译器构建的二进制代码,这包括同一编译器的不同版本(甚至可以包括使用不同命令行选项调用的同一编译器),因此您尝试做的事情的答案是明确的“不行”。原因是不同的编译器可能提供std::string的不同实现。例如,一个实现可能具有固定的静态缓冲区,而另一个版本则没有,这已经导致了不同的对象大小。还有一堆其他的东西可能会使接口不兼容,比如底层分配器、内部表示等。一些东西已经无法链接,由于名称重整或不同的私有API,这两者都保护您免受做错事情的伤害。一些注意事项:即使您没有按值而是按引用传递对象,被调用的代码也可能对此对象的外观有不同的想法。编译器提供的类型并不重要,即使您自己定义了类并使用不同版本的类定义编译了两个DLL,您也会遇到问题。如果您更改标准库实现,也会使二进制文件不兼容。其他代码位于DLL中也无关紧要,它也适用于同一可执行文件或DLL中的代码,尽管头文件和更改后的自动重新编译使这种情况变得很少见。具体针对MS Windows,您还有一个调试堆和一个发布堆,不能将在其中一个中分配的内存返回到另一个中。出于这个原因,您通常有两个DLL,一个带有“d”后缀(调试版本)和一个没有。这是编译器设置已经影响兼容性的情况,但是您也可以通过提供两个版本的DLL来解决这个问题。在某种程度上,C代码也会出现类似的问题,编译器必须同意结构布局和调用约定等等。由于年龄较大且复杂度较低,不同的C编译器实际上是兼容的。这也被认为是C相对于C ++所需的一个必要特征。